在最后 send()
之后直接 close()
套接字是明智/安全的吗?
我知道TCP应该尝试在关闭套接字后尝试在发送缓冲区中传递所有剩余数据,但是我真的可以依靠它吗?
我确保我的接收缓冲区中没有剩余数据,因此在关闭后不会发送任何RST .
在我的例子中,close在调用 exit()
之前实际上是最后一个代码语句 .
即使在发送数据的进程终止后,TCP堆栈是否会继续尝试传输数据?在通过设置SO_LINGER调用 close()
之前,自己等待任意超时是否可靠?
也就是说,应用相同的TCP超时,还是缩短?毕竟,使用大的发送缓冲区和慢速连接,实际传输所有缓冲数据的时间可能很长 .
我对收到最后一个字节的通知并不感兴趣;我只是希望他们最终尽可能可靠地到达远程主机 .
应用程序层确认不是一个选项(协议是HTTP,我正在编写一个小型服务器) .
1 回答
我一直在阅读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() .