我一直在使用一个简单的服务器,每30秒向客户端发送一个心跳数据包,然后用心跳回复数据包确认心跳。当我通过发送它SIGKILL,SIGSEGV来粗暴地终止服务器时,客户端通过select()和read()系统调用足以发现这一点。然后,我开始想知道在客户端写入其心跳回复数据包之前这样做时发生了什么,所以我在客户端代码中放置了20秒的睡眠时间,同时杀死了服务器,但发现客户端写入仍然成功。之后立即尝试第二次写入,触发了预期的SIGPIPE信号并写入返回的EPIPE。据我所知这是正常的行为,但是,出于好奇,我打印出客户端的TCP状态。原来是:套接字,TCP状态和写系统调用
- TCP_ESTABLISHED - 在发送服务器SIGKILL之前。
- TCP_CLOSE_WAIT - 在第一次客户端写入之前的服务器端SIGKILL之后。
- TCP_CLOSE - 第一次和第二次写入尝试后。
所以我的问题是:
- 为什么第一次写入没有提出SIGPIPE并返回EPIPE?
- 我可以得出结论:如果在第一次写入连接到服务器的连接关闭后,TCP状态是TCP_CLOSE,还是必须再次发送一次数据才能确定?
,我此刻明白发生了什么的示意图:
server client
[ESTABLISHED] | | [ESTABLISHED]
SIGKILL or close() --> | |
[FIN_WAIT_1] |------------FIN M------------------->| [CLOSE_WAIT]
| | ---\
[FIN_WAIT_2] |<-----------ACK M+1------------------| |
| | | a read performed after a
[TIME_WAIT] |<-----------FIN N--------------------| [LAST_ACK?] |-- serverside SIGKILL returns 0
| | | but write succeeds
|------------ACK N+1----------------->| [CLOSE] |
| | ---/
| |
| | ---\
| | [CLOSE] | After the first write returns
| | | the TCP/IP state is CLOSED
| | [CLOSE] | but even so only the a second
| | | returns EPIPE and raises SIGPIPE.
| | [CLOSE] |
| | v
[写入封闭的本地TCP套接字不失败](http:// stackoverflow。com/questions/11436013 /写封闭本地-tcp-socket-not-failing) – jxh