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 接着滑动窗口会拆包

 

缓冲区拆包.zip

 

posted on 2019-12-14 00:24  silyvin  阅读(317)  评论(0编辑  收藏  举报