2010-03-03 5 views
11

Recientemente, durante la lectura de un Socket Programming HOWTO la sección siguiente me llamó la atención:Socket Protocolo Fundamentos

Pero si va a volver a utilizar el enchufe para una nueva transferencia, tiene que darse cuenta de que no hay "EOT" (Fin de la transferencia) en un socket. Repito: si un socket send o recv regresa después de manejar 0 bytes, la conexión se ha roto. Si la conexión no se ha roto, puede esperar a recibir una llamada para siempre, porque el conector no le dirá que no hay nada más que leer (por ahora). Ahora bien, si piensa en eso un poco, se dará cuenta de una verdad fundamental de los sockets: los mensajes deben ser de longitud fija (yuck), o ser delimitados (shrug), o indicar cuánto tiempo son (mucho mejor) o finalizando la conexión. La elección es totalmente suya, (pero algunas formas son más adecuadas que otras).

En esta sección se destacan 4 posibilidades de cómo se puede escribir un "protocolo" de socket para pasar mensajes. Mi pregunta es, ¿cuál es el método preferido para usar en aplicaciones reales?

¿Es generalmente mejor incluir el tamaño del mensaje con cada mensaje (presumiblemente en un encabezado), como afirma el artículo más o menos? ¿Hay alguna situación en la que otro método sea preferible?

+0

El enlace anterior está roto. – cdosborn

+0

Se trata de la programación de socket python, el nuevo enlace es https://docs.python.org/2/howto/sockets.html –

Respuesta

5

Los protocolos comunes especifican la longitud en el encabezado o están delimitados (como HTTP, por ejemplo).

Tenga en cuenta que esto también depende de si usa sockets TCP o UDP. Como las tomas TCP son confiables, puedes estar seguro de que obtienes todo lo que introdujiste en ellas. Con UDP, la historia es diferente y más compleja.

+0

+1, con longitud fija de UDP es el camino a seguir. Si no incluye todo en un paquete, es posible que no pueda volver a armarlo. –

+1

¿Por qué importa eso, la capa de IP no reenviará el paquete UDP a su aplicación si es mordido en el camino? ¿Falta una parte es lo mismo que perderlo todo, verdad? Ha pasado mucho tiempo desde que escribí una aplicación de red, me temo. –

+2

"Dado que los enchufes TCP son confiables, puedes estar seguro de que obtienes todo lo que introdujiste en ellos" es una terrible idea errónea. Puede estar seguro de que recibe todo en el orden correcto y de que el flujo de datos comienza con lo que realmente pretendía ser el inicio, pero nunca puede estar seguro de si terminó donde se pretendía finalizar sin utilizar estructuras de protocolo a nivel de aplicación. determinar eso. –

2

Estas son nuestras elecciones con TCP. HTTP, por ejemplo, utiliza una mezcla de segunda, tercera, y adelante opción (termina doble nueva línea cabeceras de petición/respuesta, que fuerza contienen la cabecera Content-Length o indican fragmentada codificación, o podría decir Connection: close y no dar usted la longitud del contenido, pero esperamos que confíe en la lectura de EOF.)

Prefiero la tercera opción, es decir, los mensajes de autodescripción, aunque la longitud fija es fácil cuando es conveniente.

1

No sé si hay una opción preferida. En nuestra situación del mundo real (aplicación cliente-servidor), usamos la opción de enviar la longitud total del mensaje como una de las primeras piezas de datos. Es simple y funciona tanto para nuestras implementaciones TCP como UDP. Hace la lógica razonablemente "simple" al leer datos en ambas situaciones. Con TCP, la cantidad de código es bastante pequeña (en comparación). La versión de UDP es un poco (insuficiente) más compleja, pero aún depende del tamaño que se pasa en el paquete inicial para saber cuándo se han enviado todos los datos.

+0

Una buena elección. La implementación puede ser vulnerable a desbordamientos de búfer cuando los programadores no prueban con mensajes no válidos. –

2

Si está diseñando su propio protocolo, primero mire el trabajo de otras personas; puede que ya exista algo similar que podría usar 'tal cual' o readaptar y ajustar. Por ejemplo; ISO-8583 para txns financieros, HTTP o POP3 todos hacen las cosas de manera diferente, pero en formas que han demostrado funcionar ... De hecho, vale la pena mirar estas cosas de todos modos, ya que aprenderá mucho acerca de cómo se combinan los protocolos del mundo real.

Si necesita escribir su propio protocolo, entonces, en mi humilde opinión, prefiero los mensajes prefijados de longitud cuando sea posible.Son fáciles y eficientes de analizar para el receptor, pero posiblemente más difíciles de generar si es costoso determinar la longitud de los datos antes de comenzar a enviarlos.

1

La decisión debería depender de los datos que desea enviar (de qué se trata, cómo se recopila). Si los datos son de longitud fija, entonces los paquetes de longitud fija probablemente sean los mejores. Si los datos pueden ser fácilmente (no se necesita escaparse) divididos en entidades delimitadas, entonces la delimitación puede ser buena. Si conoce el tamaño de los datos cuando comienza a enviar la pieza de datos, entonces el prefijo de len puede ser incluso mejor. Si los datos enviados son siempre caracteres individuales, o incluso bits individuales (por ejemplo, "activado"/"desactivado"), todo lo que sea diferente de los mensajes de caracteres de tamaño fijo será demasiado.

También piense cómo puede evolucionar el protocolo. Las cadenas delimitadas por EOL son buenas siempre que no contengan caracteres EOL. La longitud fija puede ser buena hasta que los datos se puedan extender con algunas piezas opcionales, etc.