Windows Sockets: Bloqueo
En este artículo y en dos artículos complementarios se explican varios problemas en la programación de Windows Sockets. Este artículo trata sobre el bloqueo. Los otros problemas se tratan en los artículos: Windows Sockets: Orden de bytes y Windows Sockets: Convertir cadenas.
Si usas o derivas de la clase CAsyncSocket, deberás administrar estos problemas usted mismo. Si usa o deriva de la clase CSocket, MFC los administra por usted.
Bloqueos
Un socket puede estar en "modo de bloqueo" o "modo de no bloqueo". Las funciones de los sockets en modo de bloqueo (o sincrónico) no regresan hasta que puedan completar su acción. Esto se denomina bloqueo porque el socket cuya función se llamó no puede hacer nada ( se bloquea) hasta que la llamada se devuelve. Una llamada a la función miembro Receive
, por ejemplo, puede tardar mucho tiempo en completarse arbitrariamente, ya que espera a que se envíe la aplicación de envío (es decir, si usa CSocket
o CAsyncSocket
con bloqueo). Si un objeto CAsyncSocket
está en modo de no bloqueo (funciona de forma asincrónica), la llamada se devuelve inmediatamente y el código de error actual, recuperable con la función miembro GetLastError, es WSAEWOULDBLOCK, lo que indica que la llamada habría bloqueado si no hubiera regresado inmediatamente debido al modo. (CSocket
nunca devuelve WSAEWOULDBLOCK. La clase administra el bloqueo por usted).
El comportamiento de los sockets es diferente en sistemas operativos de 32 y 64 bits (como Windows 95 o Windows 98) que en sistemas operativos de 16 bits (como Windows 3.1). A diferencia de los sistemas operativos de 16 bits, los sistemas operativos de 32 y 64 bits usan multitareas preventivas y proporcionan multiprocesos. En los sistemas operativos de 32 y 64 bits, se pueden colocar los sockets en subprocesos de trabajo independientes. Un socket de un subproceso puede bloquearse sin interferir con otras actividades de la aplicación y sin dedicar tiempo de proceso al bloqueo. Para obtener información sobre la programación multiproceso, consulte el artículo Multithreading.
Nota:
En las aplicaciones multiproceso, se puede usar la naturaleza de bloqueo de CSocket
para simplificar el diseño del programa sin afectar a la capacidad de respuesta de la interfaz de usuario. Al controlar las interacciones del usuario en el subproceso principal y el procesamiento CSocket
en subprocesos alternativos, se pueden separar estas operaciones lógicas. En una aplicación que no es multiproceso, estas dos actividades se deben combinar y controlar como un único subproceso, lo que normalmente significa usar CAsyncSocket
para poder controlar las solicitudes de comunicaciones a petición o invalidar CSocket::OnMessagePending
para controlar las acciones del usuario durante una actividad sincrónica larga.
El resto de esta discusión es para los programadores destinados a sistemas operativos de 16 bits:
Normalmente, si se usa CAsyncSocket
, se debe evitar el uso de las operaciones de bloqueo y operar de forma asincrónica en su lugar. En operaciones asincrónicas, desde el punto en el que se recibe un código de error WSAEWOULDBLOCK después de llamar a Receive
, por ejemplo, se espera hasta que se llame a la función miembro OnReceive
para notificar que se puede volver a leer. Las llamadas asincrónicas se realizan llamando a la función de notificación de devolución de la llamada adecuada del socket, como OnReceive.
En Windows, las llamadas de bloqueo se consideran prácticas incorrectas. De forma predeterminada, CAsyncSocket admite las llamadas asincrónicas y se debe administrar el bloqueo mediante las notificaciones de devolución de llamada. Por otro lado, la clase CSocket es sincrónica. Bombea mensajes de Windows y administra el bloqueo por usted.
Para obtener más información sobre el bloqueo, consulte la especificación de Windows Sockets. Para obtener más información sobre las funciones "On", consulte Windows Sockets: notificaciones de socket y Windows Sockets: derivación de clases de socket.
Para más información, consulte: