13发送缓冲区、滑动窗口 对小于mss的包是如何拆包的
由于在之前的例子中,我们可以看到腾讯server返回的mss都是1460,windowsize 1152(接收端读缓冲,发送端写缓冲),故我们设计包大小为1300,以体现超过1152缓冲区的包,会被拆包,另外我们将客户端写入缓冲区分别设置为100和1300
1 先考虑发送缓冲区拆包,写入缓冲区100
package com.jds.test.bio.p8; /** * https://www.cnblogs.com/silyvin/articles/12037918.html * Created by joyce on 2019/11/26. */ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; public class Client { public static final int PORT = 12123; public static final int BUFFER_SIZE = 1300; public static void main(String []f) throws IOException { new Client().client(); } //客户端代码 public void client() throws UnknownHostException, IOException{ final String s1 = "49.235.75.155";// tx final String s2 = "localhost"; final String s3 = "39.100.99.222";// al // Socket s = new Socket(s1,PORT);//创建socket连接 Socket s = new Socket(); System.out.println(s.getReceiveBufferSize()); System.out.println(s.getSendBufferSize()); s.setReceiveBufferSize(100); // 这个100会先于滑动窗口导致拆包 // s.setSendBufferSize(100); s.setSendBufferSize(BUFFER_SIZE); s.connect(new InetSocketAddress(s1, PORT)); // 发送一个介于对方window 1152,与mss 1460的之间大小的包 s.getOutputStream().write(new byte[BUFFER_SIZE]); } }
package com.jds.test.bio.p8; /** * https://www.cnblogs.com/silyvin/articles/12037918.html * Created by joyce on 2019/11/26. */ import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; public class Server { public static final int PORT = 12123; public static final int BUFFER_SIZE = 500; public static void main(String [] f) throws IOException, InterruptedException { new Server().server(); } //服务端代码 public void server() throws IOException, InterruptedException{ // ServerSocket ss = new ServerSocket(PORT); ServerSocket ss = new ServerSocket(); System.out.println(ss.getReceiveBufferSize()); ss.setReceiveBufferSize(100); InetAddress bindAddr = null; ss.bind(new InetSocketAddress(bindAddr, PORT), 50); while(true) { Socket s = ss.accept(); System.out.println(s.getRemoteSocketAddress().toString()); InputStream inputStream = s.getInputStream(); byte [] bytes = new byte[BUFFER_SIZE]; int i=0; while (inputStream.read(bytes) != -1) { System.out.println(i++); } } } }
服务端:
43690
/183.192.17.180:26573
0
1
2
3
4
5
6
7
8
9
10
11
12
客户端:
131072
131072
1)可见,1300的包被拆为13个100的包,服务端历次windowsize为1152-100=1052
2)在100/1152这个比例下,服务端全程未delayed ack
2 将写入缓冲区调整为1300,考察滑动窗口1152对拆包的影响
1)可见,1152的滑动窗口把原本1300字节的包拆为1152+148,这个包虽然跨过了1300发送缓冲区大小的坎,但被滑动窗口拦下,拆了
2)服务端输出:
43690
/183.192.17.180:26595
0 第1个1152包的第一个500字节
1 第1个1152包的第二个500字节
2 第1个1152包的第三个152字节
3 第2个148字节的包
3)虽然仅修改了mac client 发送缓冲区由100到1300,但是发送端的滑动窗口由17496到了39000
结论:
1 发送缓冲区首先会拆包
2 接着滑动窗口会拆包