当我通过tcp流发送()/ write()消息时,如何确定这些字节是否成功传递?
接收器确认通过tcp接收字节,因此发送器tcp堆栈应该知道.
但是当我发送()一些字节时,send()立即返回,即使数据包无法(尚未)传递,我在linux 2.6.30上使用strace在netcat上测试,在发送一些字节之前拉出我的网线.
我只是在开发一个应用程序,其中非常重要的是知道是否已传递消息,但实现tcp功能("ack for message#123")感觉很尴尬,必须有更好的方法.
发送TCP确实知道数据何时被另一端确认,但这样做的唯一原因是它知道何时可以丢弃数据(因为其他人现在负责将数据传送到另一端的应用程序) ).
它通常不提供此信息发送应用程序,因为(尽管外表),它不会真的意味着很多发送应用程序.确认并不意味着接收应用程序已获得数据并做了一些合理的事情 - 这意味着发送TCP不再需要担心它.数据仍然可以在传输中 - 例如,在中间代理服务器内,或者在接收TCP堆栈内.
"成功接收数据"实际上是一个应用程序级别的概念 - 它的含义因应用程序而异(例如,对于许多应用程序,只有在接收到同步到磁盘后才考虑"收到"数据才有意义侧).这意味着你必须自己实现它,因为作为应用程序开发人员,你真的是唯一有能力知道如何为你的应用程序做出明智做法的人.
让接收者发回一个确认是最好的方式,即使它"感觉很尴尬".请记住,IP可能会将您的数据分成多个数据包并重新组装,如果路由器中的各种路由器具有不同的MTU,则可以在传输中多次执行此操作,因此您的"数据包"和TCP的概念可能不一致.
最好发送你的"数据包",无论是字符串,序列化对象还是二进制数据,让接收者做它需要做的任何检查才能使它成为那里,然后发回一个确认.
TCP协议非常努力地确保您的数据到达.如果存在网络问题,它将重新传输数据几次.这意味着您发送的任何内容都是缓冲的,并且没有及时的方法来确保它已到达(如果网络中断,将在2分钟后超时).
如果需要快速反馈,请使用UDP协议.它不使用任何TCP开销,但您必须自己处理所有问题.