send()后直接关闭()套接字:不安全?

时间:2012-01-15 22:44:42

标签: sockets tcp

close()之后直接send()套接字是明智/安全吗?

我知道TCP应该尝试在关闭套接字后尝试在发送缓冲区中传递所有剩余数据,但是我真的可以依靠它吗?

我确保接收缓冲区中没有剩余数据,以便在我关闭后不会发送RST。


在我的情况下,close在调用exit()之前实际上是最后一个代码语句。

即使在发送数据的进程终止后,TCP堆栈是否会继续尝试传输数据?在通过设置SO_LINGER来调用close()之前,自己等待任意超时是否可靠?

也就是说,应用相同的TCP超时,还是缩短?毕竟,使用大的发送缓冲区和慢速连接,实际传输所有缓冲数据的时间可能很长。


我对收到最后一个字节的通知并不感兴趣;我只是希望他们最终尽可能可靠地到达远程主机。

应用程序层确认不是一个选项(协议是HTTP,我正在编写一个小型服务器)。

1 个答案:

答案 0 :(得分:23)

我一直在阅读ultimate SO_LINGER page。我建议你也读它。它讨论了与TCP套接字有关的大数据传输的边缘情况。

我不是SO_LINGER的专家,但是在我的服务器代码上(仍在积极开发中)我会做以下事情:

  1. 在通过send()发送最后一个字节后,我调用“shutdown(sock,SHUT_WR)”来触发FIN发送。

  2. 然后等待对该套接字的后续recv()调用返回0(或者recv返回-1,而errno是EAGAIN / EWOULDBLOCK的其他内容)。

  3. 然后服务器在套接字上执行close()。

  4. 假设客户端在收到响应的所有字节后首先关闭套接字。

    但是我确实在最终的send()和recv()指示EOF之间执行了超时。如果客户端永远不会关闭他的连接结束,服务器将放弃等待并关闭连接。我超时为45-90秒。

    我的所有套接字都是非阻塞的,我使用poll / epoll来通知连接事件,作为提示是否有时间再次尝试调用recv()或send()。