TCP三次握手与四次挥手

说明

  1. TCP在建立连接与断开连接时报文头部的标志位与序号值分别是多少呢?
  2. 利用Java的Socket对象分别实现客户端与服务端,对进通讯过程进行数据报文捕获;
  3. 分别研究两种情况,一种是服务器与客户端都在本机,另一种是分别位于两台机器上;

Java示例代码

Client

// package com.yusian;

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

public class Client {
    public static void main(String[] args) {
        try (
                Socket socket = new Socket("127.0.0.1", 8080);
                OutputStream os = socket.getOutputStream();
                OutputStreamWriter writer = new OutputStreamWriter(os);
                InputStream is = socket.getInputStream();
                InputStreamReader reader = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(reader);
        ){
            // 终端输入对象
            Scanner sc = new Scanner(System.in);
            System.out.print("请输入:");

            // 输入消息内容,写入到输入流
            String str = sc.nextLine();
            writer.write(str);
            writer.flush();
            socket.shutdownOutput();

            // 读取客户端发送过来的消息
            String message = br.readLine();
            System.out.println(message);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Server

// package com.yusian;

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

public class Server {
    public static void main(String[] args) {
        try (
                ServerSocket ss = new ServerSocket(8080);
                Socket socket = ss.accept();
                InputStream is = socket.getInputStream();
                InputStreamReader reader = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(reader);
                OutputStream os = socket.getOutputStream();
                OutputStreamWriter writer = new OutputStreamWriter(os);
        ) {
            // 读取客户端发送过来的数据
            String s = br.readLine();
            System.out.println(s);

            // 回写给客户端信息
            writer.write("ok");
            writer.flush();
            socket.shutdownOutput();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Wireshark抓包结果分析:

127.0.0.1 —> 127.0.0.1

  • [SYN] seq = 0, ack = 0
    • [SYN, ACK] seq = 0, ack = 1
  • [ACK] seq = 1, ack = 1
  • [PSH, ACK] seq = 1, ack = 1, len = 5
    • [ACK] seq = 1, ack = 6
  • [FIN, ACK] seq = 6, ack = 1
    • [ACK] seq = 1, ack = 7
    • [PSH, ACK] seq = 1, ack = 7, len = 2
  • [ACK] seq = 7, ack = 3
    • [FIN, ACK] seq = 3, ack = 7
  • [ACK] seq = 7, ack = 4

localhost —> node.yusian.net

  • [SYN] seq = 0, ack = 0
    • [SYN, ACK] seq = 0, ack = 1
  • [ACK] seq = 1, ack = 1
  • [PSH, ACK] seq = 1, ack = 1, len = 5
  • [FIN, ACK] seq = 6, ack = 1
    • [ACK] seq = 1, ack = 6 // 这里的ack我觉得按理应该是7,可实际上是6,可能是因为多个报文同时到达,这里ack回复的是PSH标记的报文,而非FIN标记的报文
    • [PSH, ACK] seq = 1, ack = 7, len = 2
    • [FIN, ACK] seq = 3, ack = 7
  • [ACK] seq = 7, ack = 4

Leave a Reply