Averiguar si se entregó un mensaje sobre tcp

Cuando envío () / write () un mensaje a través de una transmisión tcp, ¿cómo puedo saber si esos bytes fueron entregados con éxito?

El receptor reconoce recibir los bytes a través de tcp, por lo que los remitentes tcp stack deberían saberlo.

Pero cuando envío () algunos bytes, send () devuelve inmediatamente, incluso si el paquete no pudo (aún) entregarse, lo probé en linux 2.6.30 usando strace en netcat, sacando el cable de mi red antes de enviar algunos bytes.

Solo estoy desarrollando una aplicación donde es muy importante saber si se envió un mensaje, pero la implementación de las características de tcp (“ack for message # 123”) se siente incómodo, debe haber una mejor manera.

El TCP emisor sabe cuándo los datos son reconocidos por el otro extremo, pero la única razón por la que lo hace es para saber cuándo puede descartar los datos (porque otra persona es ahora responsable de obtenerlos en la aplicación del otro lado). )

Normalmente no proporciona esta información a la aplicación de envío, porque (a pesar de las apariencias) en realidad no significaría mucho para la aplicación de envío. El reconocimiento no significa que la aplicación receptora haya obtenido los datos y haya hecho algo sensato al respecto; todo lo que significa es que el TCP emisor ya no tiene que preocuparse por ello. Los datos aún podrían estar en tránsito, por ejemplo dentro de un servidor proxy intermedio o dentro de la stack TCP receptora.

“Datos recibidos con éxito” es realmente un concepto de nivel de aplicación; lo que significa varía según la aplicación (por ejemplo, para muchas aplicaciones solo tendría sentido considerar los datos “recibidos” una vez que se han sincronizado en el disco del receptor) lado). Eso significa que tiene que implementarlo usted mismo, porque como desarrollador de aplicaciones, usted es realmente el único en posición de saber cómo hacerlo de manera sensata para su aplicación.

Hacer que el receptor devuelva un ack es la mejor manera, incluso si “se siente incómodo”. Recuerde que IP puede dividir sus datos en varios paquetes y volverlos a ensamblar, y esto podría hacerse varias veces a lo largo de una transmisión si varios enrutadores en el camino tienen diferentes MTU, por lo que su concepto de “paquete” y TCP podría estar en desacuerdo.

Es mucho mejor enviar su “paquete”, ya sea una cadena, un objeto serializado o datos binarios, y hacer que el receptor haga las comprobaciones necesarias para que esté allí, y luego devolver un acuse de recibo.

El protocolo TCP se esfuerza mucho para asegurarse de que sus datos lleguen. Si hay un problema de red, retransmitirá los datos unas pocas veces. Eso significa que todo lo que envíe se almacenará en un búfer y no hay forma oportuna de asegurarse de que haya llegado (habrá un tiempo de espera de 2 minutos más tarde si la red no funciona).

Si necesita una respuesta rápida, use el protocolo UDP. No utiliza ninguna de las tara de TCP, pero debe manejar todos los problemas usted mismo.

La capa de aplicación no tiene control sobre las notificaciones en las capas inferiores (como la capa de Transporte) a menos que se proporcionen específicamente, esto es por diseño. Si desea saber lo que TCP está haciendo en un nivel por paquete, debe averiguar en la capa en la que opera TCP; esto significa manejar encabezados TCP y datos ACK.

Sin embargo, cualquier protocolo que termine usando para transportar su carga se puede usar para pasar mensajes hacia adelante y hacia atrás a través de esa carga útil. Entonces, si se siente incómodo al usar los bits de un encabezado TCP para hacer esto, simplemente configúrelo en su aplicación. Por ejemplo:

A: Send 450 Bytes B: Recv 450 Bytes B: Send 'I got 450 Bytes' A: Recv 'B got the full message' A: Continue 

Incluso si llega hasta la capa TCP, no hay garantía de que no se encuentre en el búfer de la aplicación, entonces la aplicación se colgó antes de que pudiera procesarla. Use un acuse de recibo, eso es lo que hace todo lo demás (por ejemplo, SMTP)

Esto suena como SCTP podría ser algo para mirar; Creo que debería apoyar lo que quieras. La alternativa parece ser cambiar a UDP, y si cambias los protocolos de todos modos