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
CSocket
Requisitos
Encabezado: afxsock.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_DGRAM
Admite 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 objetoCArchive
.Nota:
La función miembro
Accept
toma una referencia a un objetoCSocket
nuevo y vacío como parámetro. Debe construir este objeto antes de llamar aAccept
. Tenga en cuenta que si este objeto de socket se sale del ámbito, la conexión se cierra. No llame aCreate
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)