假设我有一个服务器应用程序 - 使用UNIX套接字通过TCP连接。
连接是异步的 - 换句话说,客户端和服务器的套接字是非阻塞的。
假设出现以下情况:在某些情况下,服务器可能会决定将某些数据发送到已连接的客户端并立即关闭连接:使用shutdown
SHUT_RDWR
。
所以,我的问题是 - 是否有保证,当客户端调用recv
时,它会收到(由服务器发送)数据?
或者,要接收数据,必须在服务器recv
之前调用shutdown
?如果是这样,我应该做什么(或者,更确切地说,我应该怎么做),以确保客户收到数据?
答案 0 :(得分:5)
您可以使用“setsockopt(SO_LINGER)”控制此行为:
SO_LINGER 如果存在数据,则等待完成关闭功能。启用此选项时,关闭时存在未发送的数据 函数被调用,调用应用程序被阻塞 关闭功能,直到数据传输或连接 时间到。 close函数返回而不阻塞调用者。 此选项仅对流套接字有意义。
另见:
答案 1 :(得分:5)
无法保证您将收到任何数据,更不用说这些数据,但是套接字关闭时待处理的数据与所有其他数据一样受相同的保证:如果它到达它将会按顺序到达并完好无损,并受到TCP的最大努力。
NB'异步'和'非阻塞'是两个不同的东西,而不是同一个东西的两个术语。
答案 2 :(得分:3)
一旦你成功地将数据写入套接字,它就在内核的缓冲区中,它将保持不变,直到它被发送和确认。关机不会导致缓冲数据丢失。关闭套接字不会导致缓冲的数据丢失。即使发送过程的死亡也不会导致缓冲的数据丢失。
您可以使用netstat
观察缓冲区的大小。 SendQ列是内核仍希望传输的数据量。
客户端确认了所有内容后,端口将从服务器中消失。这可能在客户端读取数据之前发生,在这种情况下,它将在客户端的RecvQ中。基本上你没有什么可担心的。成功写入TCP套接字后,每个组件都尽可能地努力确保您的数据无论发送套接字和/或进程发生什么情况都能确保您的数据无损地到达目的地。
好吧,也许有一件事需要担心:如果客户端在服务器完成关闭后尝试发送任何内容,它可能会在读取套接字中的所有可用数据之前获得SIGPIPE并死掉。