客户端TCP状态装换时序图
服务器端状态装换时序图
package com.ht.web.tcp;
import java.io.IOException;
import java.net.Socket;
import java.util.Arrays;
public class TcpClient {
public static void main(String[] args) throws IOException, InterruptedException {
Socket socket = new Socket("192.168.80.110", 8080);
Thread.sleep(10000);
//10秒后关闭output输出流,会发送FIN包给服务器
//此时服务端会变为ClOSE-WAIT状态
//此时客户端会变为FIN_WAIT-2状态(此时只能接收消息,不能发送消息)
socket.shutdownOutput();
//打印结果isOutputShutdown=true | isInputShutdown=false
System.out.println("isOutputShutdown=" + socket.isOutputShutdown());
System.out.println("isInputShutdown=" + socket.isInputShutdown());
//此时仍然可以接受
while(true) {
byte[] buffer = new byte[10];
int readLen = socket.getInputStream().read(buffer);
//收到-1 说明收到服务器FIN包,此时状态切换为TIME-WAIT
//等待30秒TCP连接彻底回收
if(readLen == -1) {
System.out.println("read EOF");
Thread.sleep(10000);
if(!socket.isClosed()) {
System.out.println("server close socket");
socket.close();
}
return;
}
System.out.println(Arrays.toString(buffer));
}
}
}
package com.ht.web.tcp;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket client = serverSocket.accept();
new Thread(() -> {
System.out.println("client connect " + client.getRemoteSocketAddress());
try {
System.out.println("beginRead");
//读取到EOF,说明接收到了FIN包并返回ACK,此时状态切换为CLOSE_WAIT
//此时只能发送数据,不能再接收数据
int readLen = client.getInputStream().read();
if (readLen == -1) {
//循环三次发送数据给对方
System.out.println("read EOF");
for (int i = 0; i < 3; i++) {
client.getOutputStream().write(new byte[]{1, 2, 3, 4, 5, 7, 8, 9, 10});
Thread.sleep(5000);
}
//关闭socket,发送FIN包,此时状态LAST-ACK
//客户端发挥ACK包,状态为CLOSED
client.close();
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}