Windows Sockets: ejemplo de uso de sockets con archivos de almacenamiento

Visual Studio .NET 2003

En este artículo se presenta un ejemplo del uso de la clase CSocket. En el ejemplo se utilizan objetos CArchive para serializar datos a través de un socket. Tenga en cuenta que no se trata de la serialización bidireccional de documentos en un archivo.

En el siguiente ejemplo se ilustra la forma de utilizar el archivo de almacenamiento para enviar y recibir datos a través de objetos CSocket. El ejemplo está diseñado para que dos instancias de la aplicación (en el mismo equipo o en dos equipos diferentes de la red) intercambien datos. Una instancia envía datos y la otra los recibe y confirma la recepción. Cada una de las aplicaciones puede iniciar un intercambio y actuar como servidor o como cliente para la otra aplicación. La siguiente función está definida en la clase de vista de la aplicación:

void CBlabberView::PacketSerialize(long nPackets, CArchive& arData, 
                                    CArchive& arAck)
{
    if (arData.IsStoring())
    {
        CString strText;

        for(int p = 0; p < nPackets; p++)
        {
            BYTE bValue = (BYTE)(rand()%256);
            WORD nCopies = (WORD)(rand()%32000);

            // Send header information
            arData << bValue << nCopies;
            for(int c = 0; c < nCopies; c++)
            {
                // Send data
                arData << bValue;
            }

            Text.Format("Received Packet %d of %d  
                (Value=%d,Copies=%d)",p,nPackets,(int)bValue,nCopies);

            // Send receipt string
            arData << strText;
            arData.Flush();

            // Receive acknowledgment
            arAck >> strText;
            // display it
            DisplayMessage(strText);
        }
    }
    else
    {
        CString strText;
        BYTE bCheck;
        WORD nCopies;

        for(int p = 0; p < nPackets; p++)
        {
            // Receive header information
            arData >> bCheck >> nCopies;
            for(int c = 0; c < nCopies; c++)
            {
                // Receive data
                arData >> bValue;
                if (nCheck != bValue)
                    AfxMessageBox("Packet Failure");
            }
        }

        // Receive receipt string and display it
        arData >> strText;
        DisplayMessage(strText);

        Text.Format("Sent Packet %d of %d 
            (Value=%d,Copies=%d)",p,nPackets,(int)bValue,nCopies);

        // Send acknowledgment
        arAck << strText;
        arAck.Flush();
    }
}

Lo más importante de este ejemplo es que la estructura es paralela a la de una función Serialize de MFC. La función miembro PacketSerialize contiene una instrucción if con una cláusula else. Esta función recibe dos referencias CArchive como parámetros: arData y arAck. Si el objeto de almacenamiento arData está configurado para almacenar (enviar), se ejecutará la rama if; en cambio, si está configurado para cargar (recibir), la función ejecutará la rama else. Para obtener más información acerca de la serialización en MFC, vea el artículo Serialización.

Nota   Se supone que la misión del objeto de almacenamiento arAck es la opuesta de la de arData. Si se utiliza arData para enviar, arAck recibe, y viceversa.

Para enviar, la función ejemplo repite un bucle un número especificado de veces y, en cada repetición, genera algunos datos aleatorios con fines de demostración. La aplicación obtendría datos reales desde algún origen, como un archivo. El operador de inserción del archivo de almacenamiento arData (<<) se utiliza para enviar una secuencia de tres bloques consecutivos de datos:

  • Un "encabezado" que especifica el tipo de datos (en este caso, el valor de la variable bValue y el número de copias que se enviarán).

    Ambos elementos se generan aleatoriamente para este ejemplo.

  • El número especificado de copias de los datos.

    El bucle for interno envía bValue el número de veces especificado.

  • Una cadena llamada strText, que el receptor muestra al usuario.

Para recibir, la función actúa de forma similar, con la diferencia de que utiliza el operador de extracción del archivo de almacenamiento (>>) para obtener los datos del archivo de almacenamiento. La aplicación receptora comprueba los datos que recibe, muestra el mensaje final "Recibidos" y, a continuación, devuelve un mensaje "Enviados" para que lo muestre la aplicación emisora de datos.

En este modelo de comunicaciones, se muestra la palabra "Recibidos" (el mensaje enviado en la variable strText) en el otro extremo de la comunicación para indicar al usuario que espera los datos que recibió un número determinado de paquetes de datos. El receptor responde con una cadena similar para mostrar "Enviados" en la pantalla del usuario que envió los datos. La recepción de las dos cadenas indica que la comunicación se realizó correctamente.

Precaución   Si desarrolla un programa de cliente basado en MFC para comunicaciones con servidores establecidos (no basados en MFC), no debe enviar objetos de C++ a través del archivo de almacenamiento. A menos que el servidor sea una aplicación MFC que conozca los tipos de objetos que desea enviar, no podrá recibir ni deserializar los objetos. Un ejemplo del artículo Windows Sockets: ordenación de bytes muestra una comunicación de este tipo.

Para obtener más información, vea htonl, htons, ntohl, ntohs en la especificación de Windows Sockets. También puede obtener más información en:

Vea también

Windows Sockets en MFC | CArchive::IsStoring | CArchive::operator<< | CArchive::operator>> | CString::Format | CArchive::Flush | CObject::Serialize

Mostrar: