当应用程序调用Send之后怎么判断对方是否成功接收?
链接:https://www.zhihu.com/question/25016042/answer/73785738
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
首先,TCP是可靠的数据连接,send过去的数据,一定会被对方接收到,除非连接断开。
TCP和上层应用之间是网络层和应用层之间的关系,TCP收到的ACK只能表明对端TCP收到了相应的数据在内核缓存中,对端应用是否读取到了这条消息,是不能判断的,这点赞同
------------------------------------------------------------------------------------
题主可能对TCP中的send recv 和应用层的发送与消息接收之间的关系不是很清楚
先明确一个概念:每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应 socket的接收缓冲区内。再啰嗦一点,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。 read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,仅此而已。进程调用send发送的数据的时候,最简单情况(也是一般情况),将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回(也就是说send的返回值不能表明数据已经发送到了对端并被接收)。换句话说,send返回之时,数据不一定会发送到对端去(和 write写文件有点类似),send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。后续我会专门用一篇文章介绍 read和send所关联的内核动作。每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。
接收缓冲区被TCP和UDP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。 UDP:当套接口接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。
综上 :对方接收成功后给返回一个消息,发送方收到这个消息后就认为对方接收成功。
发送端是不管对方接收是否成功的,你是无法判断的。只有让对方接受成功后,给你发一个通知(TCP只要发送出去了,就已经发送到对方环境中了,如果是有操作的请求,那应该等待返回处理成功消息,如果是QQ这样的应用,发送出去的消息要保证对方收到,对方客户端收到后会给回应我收到了某某的哪条消息,TCP全部发送到服务器之后就确认发送过去了,但是应用层可以给个回应),已读这类功能肯定就是接受方主动发送的消息,告知我读了