TCP 客户端代码详解:握手、挥手过程解析
{"title":"TCP 客户端代码详解:握手、挥手过程解析", "description":"本文详细解析一段 TCP 客户端代码,涵盖 TCP 连接建立(三次握手)和断开(四次挥手)的完整过程。代码示例清晰易懂,并附带详细注释,适合网络编程初学者学习参考。", "keywords":"TCP, 客户端, 代码解析, 三次握手, 四次挥手, 网络编程, Socket, 数据流", "content":"这段代码是一个 TCP 客户端的实现。主要功能是进行 TCP 的握手和挥手过程。\n\n1. 首先定义了一些成员变量,包括端口号(port),IP 地址(ip),数据输入流(DataInputStream),数据输出流(DataOutputStream),Socket 对象(client)以及一些用于构造 TCP 报文段的字符串变量(seq、SYN、ack、ACK、fin 等)。\n\n2. 构造函数(Client)中首先创建一个 Socket 对象,连接到指定的 IP 地址和端口号。然后调用了 run 方法。\n\n3. run 方法中通过 Socket 对象获取数据输入流和数据输出流。然后构造了第一次握手的报文段,包括随机生成的序号(seq)、SYN 标志位和 ACK 标志位。最后将数据写入数据输出流。\n\n4. secendhand 方法中通过 Socket 对象获取数据输入流和数据输出流。然后读取了来自服务器的第二次握手报文段中的四个字段(serverSYN、serverACK、serverseq、serverack)。最后将这四个字段存入一个字符串数组并返回。\n\n5. secendPrint 方法用于打印第二次握手的报文段的内容。\n\n6. fouthsend 方法中通过 Socket 对象获取数据输入流和数据输出流。然后构造了第一次挥手的报文段,包括 fin 标志位和序号(seq)。最后将数据写入数据输出流。\n\n7. fifthhand 方法中通过 Socket 对象获取数据输入流和数据输出流。然后读取了来自服务器的第二次挥手报文段中的三个字段(RecACK2、Recseq2、Recack2)。最后将这三个字段存入一个字符串数组并返回。\n\n8. fifthPrint 方法用于打印第二次挥手的报文段的内容。\n\n9. sixthhand 方法中通过 Socket 对象获取数据输入流和数据输出流。然后读取了来自服务器的第三次挥手报文段中的三个字段(Recfin3、Recseq3、Recack3)。最后将这三个字段存入一个字符串数组并返回。\n\n10. sixthPrint 方法用于打印第三次挥手的报文段的内容。然后构造了第四次挥手的报文段,包括 ACK 标志位、序号(seq) 和确认号(ack)。最后将数据写入数据输出流。\n\njava\npublic class Client {\n int port = 8888;\n String ip = "localhost";\n DataInputStream di = null;\n DataOutputStream dou = null;\n Socket client = null; //socket 通常也称作”套接字“,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。\n\n // 构造TCP报文段\n String seq = null;// 序号\n String SYN = null;//请求同步\n String ack = null;//返回的确认号\n String ACK = null;// 确认同步\n String fin = "1";// fin=1时此报文段的发送方的数据已经发送完毕,并要求释放连接\n String serverSYN,serverACK,serverseq,serverack;\n String RecACK2,Recseq2,Recack2,Recfin3,Recseq3,Recack3;\n\n\n //初始化Socket\n public Client() throws UnknownHostException, IOException {\n client = new Socket(ip, port);\n run();\n }\n\n //将seq取出并+1形成ack\n public String seqTransferAck(String s) {\n String result = null;\n int i = Integer.parseInt(s);\n i = i + 1;\n result = String.valueOf(i);\n return result;\n }\n\n //客户端向服务器发送相关消息\n public void run() throws IOException {\n di = new DataInputStream(client.getInputStream());\n dou = new DataOutputStream(client.getOutputStream());\n //第一次握手,客户端向服务器发送的数据。seq=随机数 SYN=1 ACK=0\n seq = new Random().nextInt(1000)+"";\n ack = "0";\n SYN = "1";\n ACK = "0";\n //将要发给服务器的数据写入到数据输出流中\n dou.writeUTF(SYN);\n dou.writeUTF(ACK);\n dou.writeUTF(seq);\n\n\n }\n\n public String[] secendhand() throws Exception{\n di = new DataInputStream(client.getInputStream());\n dou = new DataOutputStream(client.getOutputStream());\n //第二次握手,读取来自服务器的数据\n String str[] = new String[4];\n serverSYN = di.readUTF();// SYN\n serverACK = di.readUTF();// ACK\n serverseq = di.readUTF();// seq\n serverack = di.readUTF();//\n str[0] = serverSYN;\n str[1] = serverACK;\n str[2] = serverseq;\n str[3] = serverack;\n return str;\n }\n\n public void secendPrint()throws Exception{\n System.out.println("第二次握手");\n System.out.println("从服务器端收到的ACK=" + serverSYN);\n System.out.println("从服务器端收到的SYN=" + serverACK);\n System.out.println("从服务器端收到的seq=" + serverseq);\n System.out.println("从服务器端收到的ack=" + serverack);\n //第三次握手,客户端向服务器发送的数据。设seq=serverack SYN=0 ACK=1 ack=seqTransferAck(serverseq)\n ACK = "1";\n SYN = "0";\n ack = seqTransferAck(serverseq);\n dou.writeUTF(ACK);\n dou.writeUTF(SYN);\n dou.writeUTF(serverack);\n dou.writeUTF(ack);\n }\n\n //[start] 四次挥手\n /**\n * TCP拆除连接的四次挥手过程\n * 第一次挥手:fin = 1,seq = u\n * 第二次挥手:ACK = 1,seq = v ack = u+1\n * 第三次挥手:fin = 1,ACK=1,seq = w,ack = u+1\n * 第四次挥手:ACK = 1,seq = u+1,ack = w+1\n */\n\n public void fouthsend() throws Exception{\n di = new DataInputStream(client.getInputStream());\n dou = new DataOutputStream(client.getOutputStream());\n seq = new Random().nextInt(1000)+"";\n dou.writeUTF(fin);\n dou.writeUTF(seq);\n }\n\n public String[] fifthhand() throws Exception{\n di = new DataInputStream(client.getInputStream());\n dou = new DataOutputStream(client.getOutputStream());\n String str[] = new String[4];\n RecACK2 = di.readUTF();\n Recseq2 = di.readUTF();\n Recack2 = di.readUTF();\n str[0] = RecACK2;\n str[1] = Recseq2;\n str[2] = Recack2;\n return str;\n }\n\n public void fifthPrint()throws Exception{\n System.out.println("第二次挥手");\n System.out.println("从服务器获得的ACK=" + RecACK2);\n System.out.println("从服务器获得的seq=" + Recseq2);\n System.out.println("从服务器获得的ack=" + Recack2);\n }\n\n public String[] sixthhand() throws Exception{\n di = new DataInputStream(client.getInputStream());\n dou = new DataOutputStream(client.getOutputStream());\n String str[] = new String[4];\n Recfin3 = di.readUTF();\n Recseq3 = di.readUTF();\n Recack3 = di.readUTF();\n str[0] = Recfin3;\n str[1] = Recseq3;\n str[2] = Recack3;\n return str;\n }\n\n public void sixthPrint()throws Exception{\n System.out.println("第三次挥手");\n System.out.println("从服务器获得的FIN=" + Recfin3);\n System.out.println("从服务器获得的seq=" + Recseq3);\n System.out.println("从服务器获得的ack=" + Recack3);\n String RecACK4 = "1";\n String Recseq4 = seqTransferAck(seq);\n String Recack4 = seqTransferAck(Recseq3);\n dou.writeUTF(RecACK4);\n dou.writeUTF(Recseq4);\n dou.writeUTF(Recack4);\n }\n\n}\n\n
原文地址: https://www.cveoy.top/t/topic/pNQN 著作权归作者所有。请勿转载和采集!