WireShark抓取TCP四次挥手报文实战

TCP四次挥手

四次挥手的流程

挥手的过程可以由任何一方发起,这里以服务器端发起为例说明:

  1. 第一次挥手:服务器端发出FIN,用来断开服务器端到客户端的数据传送,进入FIN-WAIT-1状态
  2. 第二次挥手:客户端收到服务器端的FIN后,发送ACK确认报文,进入CLOSE-WAIT状态
  3. 第三次挥手:客户端发出FIN,用来断开客户端到服务器端的数据传送,进入LAST-ACK状态
  4. 第四次挥手:服务器端收到客户端的FIN后,发送ACK确认报文,进入TIME-WAIT状态,服务器端等待2个最长报文段寿命后进入Close状态;客户端收到确认后,立刻进入Close状态。WireShark抓取TCP四次挥手报文实战_第1张图片

为什么需要四次挥手

三次握手时,服务器同时把ACK和SYN放在一起发送到了客户端那里,节省了一次报文的传送。

四次挥手时,当收到对方的FIN报文时,仅仅表示对方不再发送数据但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方ACK和FIN一般都会分开发送。

为什么客户端最后还要等待2MSL?

MSL(Maximum Segment Lifetime):报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。

2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。

WireShark抓取TCP四次挥手报文实战

可以使用下面的java代码充当服务器端:

public class SingleThreadServer2 {

    public static final int PORT = 8899;

    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = new ServerSocket();

        serverSocket.bind(new InetSocketAddress(PORT));

        System.out.println("server is start at " + PORT);

        while (true) {
            try (
                    Socket socket = serverSocket.accept();
                    InputStream inputStream = socket.getInputStream();
            ) {
                System.out.println("connect success " + socket.getPort());

                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

                System.out.println("receive from client: " + reader.readLine());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

客户端直接使用telnet,telnet localhost 8899。

第一次挥手报文如下:

WireShark抓取TCP四次挥手报文实战_第2张图片

第二次挥手报文如下:
WireShark抓取TCP四次挥手报文实战_第3张图片

第三次挥手报文如下:

WireShark抓取TCP四次挥手报文实战_第4张图片
第四次挥手报文如下:

WireShark抓取TCP四次挥手报文实战_第5张图片
更多精彩内容关注本人公众号:架构师升级之路
在这里插入图片描述

你可能感兴趣的:(计算机网络,四次挥手,tcp,WireShark,java,抓包)