18读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(四)linger
在读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(三)中,程序退出了,tcp协议还在自己跑,关键是SO_LINGER参数
默认-1,则会等发送缓冲区发完才发压箱底的fin,true时,会直接关闭连接,本文予以验证
// s.setSendBufferSize(BUFFER_SIZE); /** * 禁用nagle,可连续发包 */ s.setTcpNoDelay(true); /** * 重要参数 */ System.out.println(s.getSoLinger()); s.setSoLinger(true, 0);
由于发送缓冲区默认巨大,客户端输出:
131072
131072
-1
send + 0
send + 1
send + 2
。。
send + 99
Process finished with exit code 0
服务端输出:
43690
/183.192.17.180:25716
0
1
2
3
4
5
6
7
8
9
10
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:210)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:127)
at com.jds.test.bio.p6.Server.server(Server.java:59)
at com.jds.test.bio.p6.Server.main(Server.java:35)
结论:
1 linger默认false
2 close socket时,发fin还是rst,什么时候发,发之前是否先等缓冲区全部发送完,由tcp协议Linger参数控制
3 linger为true时,显式或隐式(程序正常退出)close socket,直接RST包,无视发送缓冲区的待发送内容,然后就没有然后了
4 对端收到rst包,无需ack
5 一端rst另一端,另一端再read,会报connection reset