通过抓包来看http三次握手的具体细节

1 篇文章 0 订阅
1 篇文章 0 订阅

需要用到的命令

lsof -p
netstat -natp
tcpdump
jps     // java-1.8.0-openjdk-devel

代码

server代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

public class SocketBioDemo {
    // 参数
    private static final int RECEIVE_BUFFER = 10;
    private static final int SO_TIMEOUT = 0;
    private static final boolean REUSE_ADDR = false;
    // 服务启动之后 太多的链接  资源不够  等待的数量 超过拒绝
    private static final int BACK_LOG = 2;

    // 通讯中的参数

    // 长链接
    private static final boolean _KEEPALIVE = false;
    // 是否优先发一个字符做嗅探
    private static final boolean _OOB = false;
    // netstat -natp 查看receive q 相关
    private static final int _REC_BUF = 20;
    // 是否重定向地址
    private static final boolean _REUSE_ADDR = false;
    // send buffer
    private static final int _SEND_BUF = 20;
    // 断开连接的速度
    private static final boolean _LINGER = true;
    //???
    private static final int _LINGER_N = 0;
    // 读取的时候 超时时间 等client多久
    private static final int _TIMEOUT = 0;
    // tcp优化算法 发送数据比较少可以缓冲
    private static final boolean _NO_DELAY = false;


    public static void main(String[] args) {

        System.out.println("server");
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(11111), BACK_LOG);
            serverSocket.setReceiveBufferSize(RECEIVE_BUFFER);
            serverSocket.setReuseAddress(REUSE_ADDR);
            serverSocket.setSoTimeout(SO_TIMEOUT);

            while (true){
                try {
                    System.in.read();
                    Socket client = serverSocket.accept();
                    System.out.println("client:" + client.getPort());
                    client.setKeepAlive(_KEEPALIVE);
                    client.setOOBInline(_OOB);
                    client.setReceiveBufferSize(_REC_BUF);
                    client.setReuseAddress(_REUSE_ADDR);
                    client.setSendBufferSize(_SEND_BUF);
                    client.setSoLinger(_LINGER, _LINGER_N);
                    client.setSoTimeout(_TIMEOUT);
                    client.setTcpNoDelay(_NO_DELAY);
                    new Thread(() -> {
                        while (true) {
                            InputStream in = null;
                            try {
                                in = client.getInputStream();
                                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                                char[] data = new char[1024];
                                int  num = reader.read(data);
                                if (num > 0) {
                                    System.out.println("data:" + num + "," + new String(data, 0, num));
                                }else if(num==0){

                                }else{
                                    System.out.println("close");
                                    client.close();
                                    break;
                                }
                            } catch (IOException e) {
                                System.out.println(e.getMessage());
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }  catch (IOException e) {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                } finally {
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        System.out.println(e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
        }catch (IOException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}

client代码(ip自己确定一下是同一个机器还是两台机器)

import java.io.*;
import java.net.Socket;

public class SocketBioClient {
    public static void main(String[] args) {
        System.out.println("start");
        try {
            Socket client = new Socket("<ip>",11111);
            client.setSendBufferSize(20);
            client.setTcpNoDelay(false);
            client.setOOBInline(false);
            OutputStream out = client.getOutputStream();
            InputStream in = System.in;
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            while (true){
                String line = reader.readLine();
                System.out.println("read:"+line);
                if(line!=null){
                    byte[] bb = line.getBytes();
                    for (byte b :bb){
                        out.write(b);
                    }
                }
            }
        }  catch (IOException e) {
            e.printStackTrace();
        }

    }
}

server启动

启动server

java Server

查看网络

netstat -natp

这时候你大概能看到这样的东西
在这里插入图片描述
这时候用jps查看下,获取到这个server的文件标识符

jps

在这里插入图片描述

lsof -p 21154

在这里插入图片描述
这一整个,就是当前server启动的记录了


启动抓包窗口

// 由于client启动的时候会发出消息,这里要先启动抓包,ifconfig 查一下自己的网卡,然后替换掉<NETWORK>
tcpdump -nn -i <NETWORK> port 11111
// 例如
tcpdump -nn -i ens3 port 11111
// 如果是同一台机器,client的ip是127.0.0.1,那就要监听lo了 例如
tcpdump -nn -i lo port 11111

client启动

java Client

开始查看抓包内容

启动内容

在这里插入图片描述

20:10:48.740386 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [S], seq 3826206646, win 43690, options [mss 65495,sackOK,TS val 976498522 ecr 0,nop,wscale 7], length 0
20:10:48.740410 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [S.], seq 2352561994, ack 3826206647, win 1152, options [mss 65495,sackOK,TS val 976498522 ecr 976498522,nop,wscale 0], length 0
20:10:48.740430 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [.], ack 1, win 342, options [nop,nop,TS val 976498522 ecr 976498522], length 0

这就是http三次握手的具体内容,具体自行查阅seq ack等

这时候再次查看网络

netstat -natp

在这里插入图片描述

之前就看到的listen

在这里插入图片描述

这里的第二个是代表内核态已经有了这个,但是目前没有分配给任何程序处理,前面的recv-q 和send-q 都是0,没有任何数据堆积

在这里插入图片描述

一个是client链接server


Client发起数据

// 例如
hello

在这里插入图片描述

这时候查看抓包

在这里插入图片描述

20:10:48.740386 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [S], seq 3826206646, win 43690, options [mss 65495,sackOK,TS val 976498522 ecr 0,nop,wscale 7], length 0
20:10:48.740410 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [S.], seq 2352561994, ack 3826206647, win 1152, options [mss 65495,sackOK,TS val 976498522 ecr 976498522,nop,wscale 0], length 0
20:10:48.740430 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [.], ack 1, win 342, options [nop,nop,TS val 976498522 ecr 976498522], length 0
20:24:14.408096 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [P.], seq 1:2, ack 1, win 342, options [nop,nop,TS val 977304190 ecr 976498522], length 1
20:24:14.408152 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [.], ack 2, win 1151, options [nop,nop,TS val 977304190 ecr 977304190], length 0
20:24:14.408221 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [P.], seq 2:3, ack 1, win 342, options [nop,nop,TS val 977304190 ecr 977304190], length 1
20:24:14.448105 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [.], ack 3, win 1150, options [nop,nop,TS val 977304230 ecr 977304190], length 0
20:24:14.448187 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [P.], seq 3:6, ack 1, win 342, options [nop,nop,TS val 977304230 ecr 977304230], length 3
20:24:14.488099 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [.], ack 6, win 1147, options [nop,nop,TS val 977304270 ecr 977304230], length 0

因为Server的参数设置,所以hello 分三次 h e llo 看到后面的length可以看的出来

再次查看网络

netstat -natp

在这里插入图片描述

这里棉的recv-q,已经变成了5 已经有数据了,但是仍旧没有程序处理


Server 接收数据

取消Server的阻塞

在这里插入图片描述

敲一下回车,这时候就不阻塞了,我们看到client发来的消息

####查看网络

netstat -natp

在这里插入图片描述

已经没有阻塞的数据了,后面也有标识,java开始处理

再次lsof查看
// jps获取文件标识符
jps
// lsof 查看状态
lsof -p 18148

在这里插入图片描述


四次挥手

在这里插入图片描述

20:10:48.740386 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [S], seq 3826206646, win 43690, options [mss 65495,sackOK,TS val 976498522 ecr 0,nop,wscale 7], length 0
20:10:48.740410 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [S.], seq 2352561994, ack 3826206647, win 1152, options [mss 65495,sackOK,TS val 976498522 ecr 976498522,nop,wscale 0], length 0
20:10:48.740430 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [.], ack 1, win 342, options [nop,nop,TS val 976498522 ecr 976498522], length 0
20:24:14.408096 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [P.], seq 1:2, ack 1, win 342, options [nop,nop,TS val 977304190 ecr 976498522], length 1
20:24:14.408152 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [.], ack 2, win 1151, options [nop,nop,TS val 977304190 ecr 977304190], length 0
20:24:14.408221 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [P.], seq 2:3, ack 1, win 342, options [nop,nop,TS val 977304190 ecr 977304190], length 1
20:24:14.448105 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [.], ack 3, win 1150, options [nop,nop,TS val 977304230 ecr 977304190], length 0
20:24:14.448187 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [P.], seq 3:6, ack 1, win 342, options [nop,nop,TS val 977304230 ecr 977304230], length 3
20:24:14.488099 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [.], ack 6, win 1147, options [nop,nop,TS val 977304270 ecr 977304230], length 0
20:48:19.676947 IP 192.168.31.151.54188 > 192.168.31.151.11111: Flags [F.], seq 6, ack 1, win 342, options [nop,nop,TS val 978749458 ecr 977304270], length 0
20:48:19.678164 IP 192.168.31.151.11111 > 192.168.31.151.54188: Flags [R.], seq 1, ack 7, win 1147, options [nop,nop,TS val 978749460 ecr 978749458], length 0

如果你看懂了以上的内容,那么,为什么握手三次即可,但是挥手却要四次,抓包为什么只看到了新增两行信息而不是四行

总结

在这里插入图片描述

额外

拥塞机制

在上文中搜索win,即可看到win的数值,win是互相通知win的大小,如果server的win过小,客户端回自己阻塞

抓包查看

  1. 启动server保持阻塞状态
  2. 启动client不停的输入
  3. 查看抓包
    在这里插入图片描述
20:55:37.852720 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [S], seq 1721479900, win 43690, options [mss 65495,sackOK,TS val 979187634 ecr 0,nop,wscale 7], length 0
20:55:37.852739 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [S.], seq 3727003628, ack 1721479901, win 1152, options [mss 65495,sackOK,TS val 979187634 ecr 979187634,nop,wscale 0], length 0
20:55:37.852753 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [.], ack 1, win 342, options [nop,nop,TS val 979187634 ecr 979187634], length 0
20:55:43.949972 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 1:2, ack 1, win 342, options [nop,nop,TS val 979193731 ecr 979187634], length 1
20:55:43.949987 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 2, win 1151, options [nop,nop,TS val 979193731 ecr 979193731], length 0
20:55:43.950045 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 2:3, ack 1, win 342, options [nop,nop,TS val 979193732 ecr 979193731], length 1
20:55:43.990076 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 3, win 1150, options [nop,nop,TS val 979193772 ecr 979193732], length 0
20:55:43.990112 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 3:75, ack 1, win 342, options [nop,nop,TS val 979193772 ecr 979193772], length 72
20:55:44.030063 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 75, win 1078, options [nop,nop,TS val 979193812 ecr 979193772], length 0
20:55:48.418981 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 75:76, ack 1, win 342, options [nop,nop,TS val 979198200 ecr 979193812], length 1
20:55:48.419026 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 76, win 1077, options [nop,nop,TS val 979198200 ecr 979198200], length 0
20:55:48.419063 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 76:77, ack 1, win 342, options [nop,nop,TS val 979198201 ecr 979198200], length 1
20:55:48.459076 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 77, win 1076, options [nop,nop,TS val 979198241 ecr 979198201], length 0
20:55:48.459104 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 77:156, ack 1, win 342, options [nop,nop,TS val 979198241 ecr 979198241], length 79
20:55:48.499079 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 156, win 997, options [nop,nop,TS val 979198281 ecr 979198241], length 0
20:55:53.954209 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 156:157, ack 1, win 342, options [nop,nop,TS val 979203736 ecr 979198281], length 1
20:55:53.954222 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 157, win 996, options [nop,nop,TS val 979203736 ecr 979203736], length 0
20:55:53.954237 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 157:158, ack 1, win 342, options [nop,nop,TS val 979203736 ecr 979203736], length 1
20:55:53.994042 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 158, win 995, options [nop,nop,TS val 979203776 ecr 979203736], length 0
20:55:53.994056 IP 192.168.31.151.40218 > 192.168.31.151.11111: Flags [P.], seq 158:238, ack 1, win 342, options [nop,nop,TS val 979203776 ecr 979203776], length 80
20:55:54.034072 IP 192.168.31.151.11111 > 192.168.31.151.40218: Flags [.], ack 238, win 915, options [nop,nop,TS val 979203816 ecr 979203776], length 0

这样就可以看出server测的win是逐渐变小的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值