20connection reset rst fin linger(二)【yetdone】
在上一节中,我们发现(三)情况是典型的4次挥手场景,却没有成功,这不是与4次挥手相悖么
原来,https://www.cnblogs.com/exmyth/p/8204724.html
前面说到出现“Connection reset”的原因是服务器关闭了Connection[调用了Socket.close()方法]。大家可能有疑问了:服务器关闭了Connection为什么会返回“RST”而不是返回“FIN”标志。原因在于Socket.close()方法的语义和TCP的“FIN”标志语义不一样:发送TCP的“FIN”标志表示我不再发送数据了,而Socket.close()表示我不在发送也不接受数据了。问题就出在“我不接受数据” 上,如果此时客户端还往服务器发送数据,服务器内核接收到数据,但是发现此时Socket已经close了,则会返回“RST”标志给客户端。当然,此时客户端就会提示:“Connection reset”。详细说明可以参考oracle的有关文档:http://docs.oracle.com/javase/1.5.0/docs/guide/net/articles/connection_release.html。
socket的close!=tcp fin,不能用于验证tcp 4次挥手,那么什么可以呢
- Use
shutdownOutput()
. This method has the same effect asclose()
in that aFIN
is sent to indicate that this peer has finished sending, but it is still possible to read from the socket until such time as the remote peer sends aFIN
and end-of-file is read from the stream. Then the socket can be closed withSocket.close()
.
https://blog.csdn.net/zhougb3/article/details/80076857
该文从文件描述符论述了shutdown与close的区别
我们将client端程序稍加改动:
int flag = 22; if(flag == 0) { } else if(flag == 11) { s.close(); } else if(flag == 12) { s.shutdownOutput(); } else if(flag == 21) { s.close(); Thread.sleep(10000); } else if(flag == 22) { s.shutdownOutput(); Thread.sleep(10000); }
0 11 12 21 都与上一节(三)一样,证明
1)close发fin包,而且不再接收
2)自然进程结束就是close
3)自然进程结束会覆盖shutdownOutput,导致不再接收
只有22 显示了客户端没有直接回绝四次挥手中服务端fin前一次psh,还发出了ack
4)证明了shutdownOutput会且只会发fin包,不会拒绝接收
但不知为何之后双方互发rst ??5次里面有一次没有互发rst