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