在close()
之后直接send()
套接字是明智/安全吗?
我知道TCP应该尝试在关闭套接字后尝试在发送缓冲区中传递所有剩余数据,但是我真的可以依靠它吗?
我确保接收缓冲区中没有剩余数据,以便在我关闭后不会发送RST。
在我的情况下,close在调用exit()
之前实际上是最后一个代码语句。
即使在发送数据的进程终止后,TCP堆栈是否会继续尝试传输数据?在通过设置SO_LINGER来调用close()
之前,自己等待任意超时是否可靠?
也就是说,应用相同的TCP超时,还是缩短?毕竟,使用大的发送缓冲区和慢速连接,实际传输所有缓冲数据的时间可能很长。
我对收到最后一个字节的通知并不感兴趣;我只是希望他们最终尽可能可靠地到达远程主机。
应用程序层确认不是一个选项(协议是HTTP,我正在编写一个小型服务器)。
答案 0 :(得分:23)
我一直在阅读ultimate SO_LINGER page。我建议你也读它。它讨论了与TCP套接字有关的大数据传输的边缘情况。
我不是SO_LINGER的专家,但是在我的服务器代码上(仍在积极开发中)我会做以下事情:
在通过send()发送最后一个字节后,我调用“shutdown(sock,SHUT_WR)”来触发FIN发送。
然后等待对该套接字的后续recv()调用返回0(或者recv返回-1,而errno是EAGAIN / EWOULDBLOCK的其他内容)。
然后服务器在套接字上执行close()。
假设客户端在收到响应的所有字节后首先关闭套接字。
但是我确实在最终的send()和recv()指示EOF之间执行了超时。如果客户端永远不会关闭他的连接结束,服务器将放弃等待并关闭连接。我超时为45-90秒。
我的所有套接字都是非阻塞的,我使用poll / epoll来通知连接事件,作为提示是否有时间再次尝试调用recv()或send()。