Windows Sockets: Cómo funcionan los Sockets con archivos

En este artículo se explica cómo se combina un objeto CSocket, un objeto CSocketFile y un objeto CArchive para simplificar el envío y la recepción de datos a través de Windows Socket.

El artículo Windows Sockets: Ejemplo de sockets que usan archivos presenta la función PacketSerialize. El objeto de archivo del ejemplo PacketSerialize funciona de forma muy similar a un objeto de archivo pasado a una función Serialize de MFC. La diferencia esencial es que, para los sockets, el archivo se adjunta no a un objeto CFile estándar (normalmente asociado a un archivo de disco), sino a un objeto CSocketFile. En lugar de conectarse a un archivo de disco, el objeto CSocketFile se conecta a un objeto CSocket.

Un objeto CArchive administra un búfer. Cuando el búfer de un archivo de almacenamiento (envío) está lleno, un objeto asociado CFile escribe el contenido del búfer. Vaciar el búfer de un archivo adjunto a un socket equivale a enviar un mensaje. Cuando el búfer de un archivo de carga (recepción) está lleno, el CFile objeto deja de leer hasta que el búfer vuelva a estar disponible.

La clase CSocketFile se deriva de CFile, pero no admite funciones miembro de CFile, como las funciones de posicionamiento (Seek, GetLength, SetLengthetc.), las funciones de bloqueo (LockRange, UnlockRange) o la función GetPosition. Todo lo que el objeto CSocketFile debe realizar es escribir o leer secuencias de bytes en o desde el objeto asociado CSocket. Dado que un archivo no está implicado, las operaciones como Seek y GetPosition no tienen sentido. CSocketFile se deriva de CFile, por lo que normalmente heredaría todas estas funciones miembro. Para evitar esto, las funciones miembro no admitidas CFile se invalidan en CSocketFile para iniciar una excepción CNotSupportedException.

El objeto CSocketFile llama a funciones miembro de su objeto CSocket para enviar o recibir datos.

En la ilustración siguiente se muestran las relaciones entre estos objetos en ambos lados de la comunicación.

CArchive, CSocketFile, and CSocket.
CArchive, CSocketFile y CSocket

El propósito de esta complejidad aparente es blindarle de la necesidad de administrar los detalles del socket usted mismo. Cree el socket, el archivo y el almacenamiento de archivo y, a continuación, comience a enviar o recibir datos insertándolo en el archivo o extrayéndolos del archivo. CArchive, CSocketFile y CSocket administran los detalles en segundo plano.

Un objeto CSocket es realmente un objeto de dos estados: a veces asincrónico (el estado habitual) y a veces sincrónico. En su estado asincrónico, un socket puede recibir notificaciones asincrónicas del marco. Sin embargo, durante una operación como recibir o enviar datos, el socket se vuelve sincrónico. Esto significa que el socket no recibirá más notificaciones asincrónicas hasta que se haya completado la operación sincrónica. Dado que cambia los modos, puede, por ejemplo, hacer algo parecido a lo siguiente:

void CMySocket::OnReceive(int nErrorCode)
{
   if (0 == nErrorCode)
   {
      CSocketFile file(this);
      CArchive ar(&file, CArchive::load);
      CString str;

      ar >> str;
   }
}

Si CSocket no se implementó como un objeto de dos estados, es posible recibir notificaciones adicionales para el mismo tipo de evento mientras procesaba una notificación anterior. Por ejemplo, puede recibir una notificación OnReceive al procesar un OnReceive. En el fragmento de código anterior, la extracción str del archivo podría provocar recursividad. Al cambiar de estado, CSocket evita la recursividad evitando notificaciones adicionales. La regla general no es ninguna notificación dentro de las notificaciones.

Nota:

También se puede usar CSocketFile como un archivo (limitado) sin un objeto CArchive. De forma predeterminada, el parámetro bArchiveCompatible del constructor CSocketFile es TRUE. Esto especifica que el objeto de archivo es para su uso con un archivo. Para usar el objeto de archivo sin un archivo, pase FALSE en el parámetro bArchiveCompatible.

En su modo "compatible con el archivo", un objeto CSocketFile proporciona un mejor rendimiento y reduce el peligro de un "interbloqueo". Un interbloqueo se produce cuando los sockets de envío y recepción están esperando entre sí o esperando un recurso común. Esta situación podría producirse si el objeto CArchive funcionaba con la forma CSocketFile en que lo hace con un objeto CFile. Con CFile, el archivo puede suponer que si recibe menos bytes de los solicitados, se ha alcanzado el final del archivo. Sin embargo, con CSocketFile, los datos se basan en mensajes; el búfer puede contener varios mensajes, por lo que recibir menos del número de bytes solicitados no implica el final del archivo. La aplicación no se bloquea en este caso, ya que puede con CFile, y puede continuar leyendo mensajes desde el búfer hasta que el búfer esté vacío. La función IsBufferEmpty de CArchive es útil para supervisar el estado del búfer del archivo en tal caso.

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

Consulte también

Windows Sockets en MFC
CObject::Serialize