Windows Sockets: Orden de bytes

En este artículo y en dos artículos complementarios se explican varios problemas en la programación de Windows Sockets. En este artículo se trata el orden de bytes. Los demás problemas se tratan en los artículos: Windows Sockets: Bloqueo y Windows Sockets: Conversión de 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.

ordenación de bytes

A veces, diferentes arquitecturas de máquina almacenan datos mediante órdenes de bytes diferentes. Por ejemplo, las máquinas basadas en Intel almacenan datos en el orden inverso de las máquinas Macintosh (Motorola). El orden de bytes intel, denominado "little-Endian", también es el inverso del orden "big-Endian" estándar de red. En la tabla siguiente se explican estos términos.

Orden de bytes little-Endian y big-Endian

Ordenación de bytes Significado
Big-Endian El byte más significativo está en el extremo izquierdo de una palabra.
Little-Endian El byte más significativo está en el extremo derecho de una palabra.

Normalmente, no tiene que preocuparse por la conversión del orden de bytes de los datos que envía y recibe a través de la red, pero hay situaciones en las que debe convertir los órdenes de bytes.

Cuándo debe convertir los órdenes de bytes

Debe convertir los órdenes de bytes en las situaciones siguientes:

  • Pasa información que la red debe interpretar, a diferencia de los datos que envía a otra máquina. Por ejemplo, puede pasar puertos y direcciones que la red debe comprender.

  • La aplicación de servidor con la que se comunica no es una aplicación MFC (y no tiene código fuente de ella). Esto llama a conversiones de orden de bytes si las dos máquinas no comparten el mismo orden de bytes.

Cuándo no es necesario convertir los órdenes de bytes

Puede evitar el trabajo de convertir los órdenes de bytes en las situaciones siguientes:

  • Las máquinas de ambos extremos pueden aceptar no intercambiar bytes y ambas máquinas usan el mismo orden de bytes.

  • El servidor con el que se comunica es una aplicación MFC.

  • Tiene código fuente para el servidor con el que se comunica, por lo que puede indicar explícitamente si debe convertir órdenes de bytes o no.

  • Puede portar el servidor a MFC. Esto es bastante fácil de hacer y el resultado suele ser código más pequeño y más rápido.

Al trabajar con CAsyncSocket, debe administrar las conversiones de orden de bytes necesarias usted mismo. Windows Sockets estandariza el modelo de orden de bytes "big-Endian" y proporciona funciones para convertir entre este orden y otros. Sin embargo, CArchive que se usa con CSocket, usa el orden opuesto ("little-Endian"), pero CArchive se encarga de los detalles de las conversiones de orden de bytes de forma automática. Con este orden estándar en las aplicaciones, o mediante funciones de conversión de orden de bytes de Windows Sockets, puede hacer que el código sea más portátil.

El caso ideal para utilizar sockets de MFC es cuando se escribe en ambos extremos de la comunicación y se usa MFC en ambos extremos. Si está escribiendo una aplicación que se comunicará con aplicaciones que no son MFC, como un servidor FTP, probablemente tendrá que administrar el intercambio de bytes antes de pasar datos al objeto de archivo, mediante las rutinas de conversión de Windows Sockets ntohs, ntohl, htonsy htonl. Más adelante se muestra un ejemplo de estas funciones usadas para comunicarse con una aplicación que no es MFC.

Nota:

Cuando el otro extremo de la comunicación no es una aplicación MFC, también debe evitar el streaming de objetos de C++ derivados del CObject en su archivo, porque el receptor no podrá controlarlos. Vea la nota en Windows Sockets: Usar sockets con archivos.

Para obtener más información sobre las órdenes de bytes, consulte la especificación de Windows Sockets, disponible en Windows SDK.

Ejemplo de conversión de Byte-Order

En el ejemplo siguiente se muestra una función de serialización para un objeto CSocket que usa un archivo. También se muestra el uso de las funciones de conversión de orden de bytes en la API de Windows Sockets.

En este ejemplo se presenta un escenario en el que escribe a un cliente que se comunica con una aplicación de servidor que no es MFC para la que no tiene acceso al código fuente. En este escenario, debe suponer que el servidor que no es MFC usa el orden de bytes de red estándar. En cambio, la aplicación cliente MFC usa un objeto CArchive con un objeto CSocket y CArchive usa el orden de bytes "little-Endian", lo contrario al estándar de red.

Supongamos que el servidor que no es MFC con el que tiene previsto comunicarse tiene un protocolo establecido para un paquete de mensajes como el siguiente:

struct Message
{
   long MagicNumber;
   unsigned short Command;
   short Param1;
   long Param2;
};

En términos de MFC, esto se expresaría de la siguiente manera:

struct Message
{
   long m_lMagicNumber;
   short m_nCommand;
   short m_nParam1;
   long m_lParam2;

   void Serialize(CArchive &ar);
};

En C++, un elemento struct es en esencia lo mismo que una clase. La estructura Message puede tener funciones miembro, como la función miembro Serialize declarada anteriormente. La función miembro Serialize podría tener este aspecto:

void Message::Serialize(CArchive &ar)
{
   if (ar.IsStoring())
   {
      ar << (DWORD)htonl(m_lMagicNumber);
      ar << (WORD)htons(m_nCommand);
      ar << (WORD)htons(m_nParam1);
      ar << (DWORD)htonl(m_lParam2);
   }
   else
   {
      WORD w;
      DWORD dw;
      ar >> dw;
      m_lMagicNumber = ntohl((long)dw);
      ar >> w;
      m_nCommand = ntohs((short)w);
      ar >> w;
      m_nParam1 = ntohs((short)w);
      ar >> dw;
      m_lParam2 = ntohl((long)dw);
   }
}

En este ejemplo se llama a conversiones de orden de bytes de datos porque hay una clara discrepancia entre el orden de bytes de la aplicación de servidor que no es MFC en un extremo y el CArchive utilizado en la aplicación cliente MFC en el otro extremo. En el ejemplo se muestran varias de las funciones de conversión de orden de bytes que proporciona Windows Sockets. En la siguiente tabla se describen estas funciones.

Funciones de conversión de Windows Sockets Byte-Order

Función Propósito
ntohs Convierta una cantidad de 16 bits del orden de bytes de red para hospedar el orden de bytes (big-Endian a little-Endian).
ntohl Convierta una cantidad de 32 bits del orden de bytes de red para hospedar el orden de bytes (big-Endian a little-Endian).
Htons Convierta una cantidad de 16 bits del orden de bytes del anfitrión al orden de bytes de red (little-Endian a big-Endian).
Htonl Convierta una cantidad de 32 bits del orden de bytes del anfitrión al orden de bytes de red (little-Endian a big-Endian).

Otro punto de este ejemplo es que, cuando la aplicación de socket en el otro extremo de la comunicación es una aplicación que no es MFC, debe evitar hacer algo parecido a lo siguiente:

ar << pMsg;

donde pMsg es un puntero a un objeto de C++ derivado de la clase CObject. Esto enviará información adicional de MFC asociada a objetos y el servidor no la comprenderá, como lo haría si fuera una aplicación MFC.

Para más información, consulte:

Consulte también

Windows Sockets en MFC