Clase CSocket

Se deriva de CAsyncSocket, hereda su encapsulación de la API de Windows Sockets y representa un nivel superior de abstracción que el de un objeto CAsyncSocket.

Sintaxis

class CSocket : public CAsyncSocket

Miembros

Constructores públicos

Nombre Descripción
CSocket::CSocket Construye un objeto CSocket.

Métodos públicos

Nombre Descripción
CSocket::Attach Asocia un identificador SOCKET a un objeto CSocket.
CSocket::CancelBlockingCall Cancela una llamada de bloqueo que está actualmente en curso.
CSocket::Create Crea un socket.
CSocket::FromHandle Devuelve un puntero a un objeto CSocket, dado un identificador SOCKET.
CSocket::IsBlocking Determina si una llamada de bloqueo está en curso.

Métodos protegidos

Nombre Descripción
CSocket::OnMessagePending Se llama para procesar los mensajes pendientes mientras se espera a que se complete una llamada de bloqueo.

Comentarios

CSocket funciona con clases CSocketFile y CArchive para administrar el envío y la recepción de datos.

Un objeto CSocket también proporciona bloqueo, que es esencial para la operación sincrónica de CArchive. Las funciones de bloqueo, como Receive, Send, ReceiveFrom, SendTo y Accept (todas heredadas de CAsyncSocket), no devuelven un error WSAEWOULDBLOCK en CSocket. En su lugar, estas funciones esperan hasta que se completa la operación. Además, la llamada original finalizará con el error WSAEINTR si se llama a CancelBlockingCall mientras una de estas funciones está bloqueando.

Para usar un objeto CSocket, llame al constructor y, luego, llame a Create para crear el identificador subyacente SOCKET (tipo SOCKET). Los parámetros predeterminados de Create crean un socket de flujo, pero si no usa el socket con un objeto CArchive, puede especificar un parámetro para crear un socket de datagrama en su lugar, o enlazar con un puerto específico para crear un socket de servidor. Conéctese a un socket de cliente mediante Connect en el lado cliente y Accept en el lado servidor. A continuación, cree un objeto CSocketFile y asócielo al objeto CSocket en el constructor CSocketFile. Luego, cree un objeto CArchive para enviar y otro para recibir datos (según sea necesario) y asócielos al objeto CSocketFile en el constructor CArchive. Cuando se completen las comunicaciones, destruya los objetos CArchive, CSocketFile y CSocket. El tipo de datos SOCKET se describe en el artículo Windows Sockets: Información de contexto.

Cuando se usa CArchive con CSocketFile y CSocket, podría encontrarse con una situación en la que CSocket::Receive entra en un bucle (por PumpMessages(FD_READ)) esperando la cantidad solicitada de bytes. Esto se debe a que los sockets de Windows solo permiten una llamada de recepción por notificación FD_READ, pero CSocketFile y CSocket permiten varias llamadas de recepción por FD_READ. Si recibe una llamada FD_READ cuando no hay datos que leer, la aplicación se bloquea. Si nunca recibe otra llamada FD_READ, la aplicación deja de comunicarse a través del socket.

Puede resolver este problema como se indica a continuación. En el método OnReceive de la clase de socket, llame a CAsyncSocket::IOCtl(FIONREAD, ...) antes de llamar al método Serialize de la clase de mensaje cuando los datos que esperan a ser leídos del socket superen el tamaño de un paquete TCP (unidad de transmisión máxima del medio de red, normalmente al menos 1096 bytes). Si el tamaño de los datos disponibles es menor que el necesario, espere a que se reciban todos los datos y solo inicie la operación de lectura.

En el ejemplo siguiente, m_dwExpected es el número aproximado de bytes que el usuario espera recibir. Se supone que se declara en otra parte del código.

void CChatSocket::OnReceive(int nErrorCode)
{
   CSocket::OnReceive(nErrorCode);

   DWORD dwReceived;

   if (IOCtl(FIONREAD, &dwReceived))
   {
      if (dwReceived >= m_dwExpected) // Process only if you have enough data
         m_pDoc->ProcessPendingRead();
   }
   else
   {
      // Error handling here
   }
}

Nota:

Al usar sockets de MFC en subprocesos secundarios en una aplicación de MFC vinculada estáticamente, debe llamar a AfxSocketInit en cada subproceso que use sockets para inicializar las bibliotecas de sockets. De manera predeterminada, se llama a AfxSocketInit solo en el subproceso principal.

Para más información, consulte Windows Sockets en MFC, Windows Sockets: Uso de sockets con archivos, Windows Sockets: Cómo funcionan los sockets con archivos, Windows Sockets: Secuencia de operaciones, Windows Sockets: Ejemplo de sockets que usan archivos.

Jerarquía de herencia

CObject

CAsyncSocket

CSocket

Requisitos

Encabezadoafxsock.h:

CSocket::Attach

Llame a esta función miembro para asociar el identificador hSocket a un objeto CSocket.

BOOL Attach(SOCKET hSocket);

Parámetros

hSocket
Contiene un identificador a un socket.

Valor devuelto

Es distinto de cero si la función se realiza correctamente.

Comentarios

El identificador SOCKET se almacena en el miembro de datos m_hSocket del objeto.

Para más información, consulte Windows Sockets: Uso de sockets con archivos.

Ejemplo

class CSockThread : public CWinThread
{
public:
   SOCKET m_hConnected;

protected:
   CChatSocket m_sConnected;

   // remainder of class declaration omitted.

 

BOOL CSockThread::InitInstance()
{
   // Attach the socket object to the socket handle
   // in the context of this thread.
   m_sConnected.Attach(m_hConnected);
   m_hConnected = NULL;

   return TRUE;
}

 

// This listening socket has been constructed
// in the primary thread.
void CListeningSocket::OnAccept(int nErrorCode)
{
   UNREFERENCED_PARAMETER(nErrorCode);

   // This CSocket object is used just temporarily
   // to accept the incoming connection.
   CSocket sConnected;
   Accept(sConnected);

   // Start the other thread.
   CSockThread *pSockThread = (CSockThread*)AfxBeginThread(
       RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
   if (NULL != pSockThread)
   {
      // Detach the newly accepted socket and save
      // the SOCKET handle in our new thread object.
      // After detaching it, it should no longer be
      // used in the context of this thread.
      pSockThread->m_hConnected = sConnected.Detach();
      pSockThread->ResumeThread();
   }
}

CSocket::CancelBlockingCall

Llame a esta función miembro para cancelar una llamada de bloqueo actualmente en curso.

void CancelBlockingCall();

Comentarios

Esta función cancela cualquier operación de bloqueo pendiente para este socket. La llamada de bloqueo original finalizará lo antes posible con el error WSAEINTR.

En el caso de una operación Connect de bloqueo, la implementación de Windows Sockets finalizará la llamada de bloqueo lo antes posible, pero quizás los recursos de socket no se puedan liberar hasta que se haya completado (y luego se haya restablecido) la conexión o se agote el tiempo de espera. Es probable que esto solo se advierta si la aplicación intenta abrir inmediatamente un nuevo socket (si no hay sockets disponibles), o conectarse al nodo del mismo nivel.

Cancelar cualquier operación distinta de Accept puede dejar al socket en un estado indeterminado. Si una aplicación cancela una operación de bloqueo en un socket, la única operación que la aplicación puede confiar en realizar en el socket es una llamada a Close, aunque otras operaciones pueden funcionar en algunas implementaciones de Windows Sockets. Si quiere una portabilidad máxima para la aplicación, debe tener cuidado de no confiar en realizar operaciones después de una cancelación.

Para más información, consulte Windows Sockets: Uso de sockets con archivos.

CSocket::Create

Llame a la función miembro Create después de construir un objeto de socket para crear el socket de Windows y asociarlo.

BOOL Create(
    UINT nSocketPort = 0,
    int nSocketType = SOCK_STREAM,
    LPCTSTR lpszSocketAddress = NULL);

Parámetros

nSocketPort
Un puerto determinado que se usará con el socket o 0 si quiere que MFC seleccione un puerto.

nSocketType
SOCK_STREAM o SOCK_DGRAM.

lpszSocketAddress
Puntero a una cadena que contiene la dirección de red del socket conectado, compuesta de números separados por puntos, como "128.56.22.8". Pasar la cadena NULL para este parámetro indica que la instancia CSocket debe escuchar la actividad del cliente en todas las interfaces de red.

Valor devuelto

Distinto de cero si la función es correcta; de lo contrario, 0. Además, se puede recuperar un código de error específico mediante una llamada a GetLastError.

Comentarios

Create llama entonces a Bind para enlazar el socket a la dirección especificada. Se admiten los siguientes tipos de socket:

  • SOCK_STREAM Proporciona secuencias de bytes secuenciadas, confiables y bidireccionales basadas en conexiones. Usa el Protocolo de control de transmisión (TCP) para la familia de direcciones de Internet.

  • SOCK_DGRAMAdmite datagramas, que son búferes no confiables sin conexión con una longitud máxima fija (normalmente corta). Usa el Protocolo de datagrama de usuario (UDP) para la familia de direcciones de Internet. Para usar esta opción, no debe usar el socket con un objeto CArchive.

    Nota:

    La función miembro Accept toma una referencia a un objeto CSocket nuevo y vacío como parámetro. Debe construir este objeto antes de llamar a Accept. Tenga en cuenta que si este objeto de socket se sale del ámbito, la conexión se cierra. No llame a Create para este nuevo objeto de socket.

Para más información sobre los sockets de flujo y datagrama, consulte los artículos Windows Sockets: Información de contexto, Windows Sockets: Puertos y direcciones de sockets y Windows Sockets: Uso de sockets con archivos.

CSocket::CSocket

Construye un objeto CSocket.

CSocket();

Comentarios

Después de la construcción, debe llamar a la función miembro Create.

Para más información, consulte Windows Sockets: Uso de sockets con archivos.

CSocket::FromHandle

Devuelve un puntero a un objeto CSocket.

static CSocket* PASCAL FromHandle(SOCKET hSocket);

Parámetros

hSocket
Contiene un identificador a un socket.

Valor devuelto

Puntero a un objeto CSocket o NULL si no hay ningún objeto CSocket asociado a hSocket.

Comentarios

Cuando se proporciona un identificador SOCKET, si un objeto CSocket no está asociado al identificador, la función miembro devuelve NULL y no crea un objeto temporal.

Para más información, consulte Windows Sockets: Uso de sockets con archivos.

CSocket::IsBlocking

Llame a esta función miembro para determinar si hay una llamada de bloqueo en curso.

BOOL IsBlocking();

Valor devuelto

Distinto de cero si el socket está bloqueando; de lo contrario, 0.

Comentarios

Para más información, consulte Windows Sockets: Uso de sockets con archivos.

CSocket::OnMessagePending

Invalide esta función miembro para buscar mensajes concretos de Windows y responder a ellos en el socket.

virtual BOOL OnMessagePending();

Valor devuelto

Distinto de cero si se ha controlado el mensaje; de lo contrario, 0.

Comentarios

Se trata de una invalidación avanzada.

El marco llama a OnMessagePending mientras el socket está bombeando mensajes de Windows para darle la oportunidad de tratar con los mensajes de interés para la aplicación. Para ver ejemplos de cómo puede usar OnMessagePending, consulte el artículo Windows Sockets: Derivación de clases de socket.

Para más información, consulte Windows Sockets: Uso de sockets con archivos.

Consulte también

CAsyncSocket (clase)
Gráfico de jerarquías
CAsyncSocket (clase)
CSocketFile (clase)