This article will capture packets on a simple TCP echo server and client to analyze the basic process of a successful and ideal TCP session, packet capture results that fail multiple times or are inconsistent with expectations will be analyzed in the next blog
The compiling environment of this program is:
Linux version 3.16.4-1-arch
GCC version 4.9.1 20140903 (prerelease)
Glibc 2.18
The server code is as follows:
1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <arpa/inet.h> 5 #include <netinet/in.h> 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h>10 11 #define ERR_EXIT(exp) 12 do13 {14 perror(exp);15 exit(EXIT_FAILURE);16 }while(0)17 18 #define BUFSIZE 102419 20 int main(int argc, char *argv[])21 {22 if(argc != 2)23 ERR_EXIT("Usage: a.out <port>");24 25 int server_sock;26 int client_sock;27 struct sockaddr_in server_addr;28 struct sockaddr_in client_addr;29 socklen_t server_len;30 socklen_t client_len;31 32 server_sock = socket(PF_INET, SOCK_STREAM, 0);33 if(server_sock == -1)34 ERR_EXIT("socket");35 36 memset(&server_addr, 0, sizeof(server_addr));37 server_addr.sin_family = AF_INET;38 server_addr.sin_addr.s_addr = INADDR_ANY;39 server_addr.sin_port = htons(atoi(argv[1]));40 server_len = sizeof(server_addr);41 client_len = sizeof(client_addr);42 43 if(bind(server_sock, (struct sockaddr*)&server_addr, server_len) == -1)44 ERR_EXIT("bind");45 46 if(listen(server_sock, 5) == -1)47 ERR_EXIT("listen");48 49 client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_len);50 if(client_sock == -1)51 ERR_EXIT("accept");52 char buffer[BUFSIZE];53 read(client_sock, buffer, BUFSIZE);54 write(client_sock, buffer, strlen(buffer));55 56 sleep(3);57 close(client_sock);58 close(server_sock);59 return 0;60 }
The client code is as follows:
1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <arpa/inet.h> 5 #include <netinet/in.h> 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h>10 11 #define ERR_EXIT(exp) 12 do13 {14 perror(exp);15 exit(EXIT_FAILURE);16 }while(0)17 18 #define BUFSIZE 102419 20 int main(int argc, char *argv[])21 {22 if(argc != 3)23 ERR_EXIT("Usage: a.out <server_ip> <port>");24 25 int server_sock;26 struct sockaddr_in server_addr;27 socklen_t server_len;28 29 server_sock = socket(PF_INET, SOCK_STREAM, 0);30 if(server_sock == -1)31 ERR_EXIT("socket");32 33 server_addr.sin_family = AF_INET;34 server_addr.sin_addr.s_addr = inet_addr(argv[1]);35 server_addr.sin_port = htons(atoi(argv[2]));36 server_len = sizeof(server_addr);37 38 if(connect(server_sock, (struct sockaddr*)&server_addr, server_len) == -1)39 ERR_EXIT("connect");40 41 char buffer[BUFSIZE] = "Hello World!";42 write(server_sock, buffer, strlen(buffer));43 memset(buffer, 0, BUFSIZE);44 read(server_sock, buffer, BUFSIZE);45 printf("%s\n", buffer);46 47 sleep(1);48 close(server_sock);49 return 0;50 }
First, the packet capture result is displayed. This is an ideal situation that fully complies with the book theory. The next blog will use the debugger and other means to create an unsatisfactory situation and analyze its behavior, therefore, the structure of TCP packets is not discussed. The win field of TCP packets is used for sliding window control. This article does not cover
First, the basic process of a TCP session should be divided into the following three steps:
- Establish a connection with the peer socket
- Exchange data with the other socket
- Disconnect from the socket of the other party
The following section analyzes the packet capture results to find out what actually happened in the three steps, the no serial number obtained by packet capture is not the same as the seq and ACK serial number in the TCP packet. Because I used SSH to connect to the test machine for control, the packet capture software captured together with the SSH data packet, data packet sequence numbers related to our test content are not consecutive, but this does not affect our analysis and understanding.
- 22nd data packet. The client sends the SYN to the server. The surface message type is SYN, that is, synchronous Message, seq = 0. This is the message generated when the client requests the connection for the first time.
- SEQ indicates that "the seq sent from the client to the server is 0 and the length of the data packet is 0, waiting for the server to confirm receipt and requestClient to serverSend 1 data packet"
- The server receives the connection request SYN and responds. In the response packet, SYN and ACK are set to SYN + ACK, seq = 0, ACK =
- SEQ indicates that "the server will send a data packet with a seq of 0 length to the client, waiting for the client to confirm receipt and sending the requestSend the server to the clientSEQ is 1 packet"
- Ack indicates that "the server has receivedClient to serverSEQ is a data packet with a length of 0, and the client can send a data packet with a seq of 1"
It should be noted that in the above article, I used "The seq from A to B is n and the length is K packet", which is very wordy because
- The increase in seq and ACK values is not based on the increase in the number of data packets. The increment is the number of transmitted data bytes, that is, Len. The growth rule is ACK = seq + Len + 1, this statement conflicts with the subsequent results and will be corrected or explained after further understanding.
- Unlike the description in books, the seq of SYN packets in book descriptions is different from that of SYN + ACK packets, this leads to the illusion that "sending data packets from client sockets and server sockets is in a linear space". The packet capture result is shown here, the client seq and server seq are independent in two linear spaces and do not interfere with each other. The standard documents of the TCP protocol are not viewed.
- The client receives the SYN + ACK message from the server and replies with Ack. seq is 1 and Ack is 1. For more information, see the preceding section,
And 25 are the first steps in the basic process of TCP sessions:Establish a connection with the peer socketIn this process, a total of three data packets are transmitted, which is also knownThree-way handshake
- Packet No. 26 is sent from the client to the server, Psh, ack, seq = 1, ACK = 1, Len = 12
- The 27 th packet is sent from the server to the client. The Ack is set to 1, seq = 1, ACK = 13. It can be seen that the server receives a data packet with a length of 12 from the client, the client is notified to send 13 data packets, which confirms that the incremental data packet seq depends on the number of transmitted bytes.
- The 28 th packet is sent from the server to the client, that is, the bounce data, Psh, ack, seq = 1, ACK = 13, Len = 13,
- Two points can be obtained from this package.
- When a request packet is not received, one party in the TCP session will request the packet again.
- One Party of a TCP session will not assume that "a packet has been requested and will receive it later"
- Looking back at the previous packages, it is not difficult to find that all TCP packets have seq and ACK values. Therefore, we can guess that seq and ACK are important guarantees and dependencies for connection-oriented TCP session reliability, no standard documents are found.
- The LEN = 13 of this data packet, and the Len packet sent from the client is indeed 12. This is a strange phenomenon. Check the data segments of packets 26 and 28 to find the differences.
- 26: 48: 65: 6C: 6C: 6f: 20: 57: 6f: 72: 6C: 64: 21
- 28: 48: 65: 6C: 6C: 6f: 20: 57: 6f: 72: 6C: 64: 21: 04
- The last 04 is added, and ASCII is expressed as EOT (end of transmission). Here, we have doubts for the time being and will fill in holes later.
- Package 29 is sent from the client to the server. Ack is set to seq = 13 and ACK = 14, indicating that the client successfully receives the data from the server.
The four data packets 26, 27, 28, and 29 show the process of a data exchange between the client and server. The two data packets return and change according to the actual business logic. This is the second step in the TCP session:Exchange data with the other socket
- Package 32: the client is sent to the server, and the fin and ACK positions indicate that the connection is about to be disconnected, waiting for the server to respond.
- Package 34, the server sends to the client, and the Ack is set to respond to the fin request of the client.
- Package 36, the server is sent to the client, and the fin and ACK positions indicate that the server will also be disconnected from the client and wait for the client to respond.
- Package 37: the client sends the ACK to the server, responds to the disconnection request from the server, and truly disconnects the server (this is not exact, but this article will not go into detail)
Packet 32, 34, 36, and 37 implements the third step in a TCP session:Disconnect from the socket of the other partyThis process passes through four data packets, which are also knownFour WavesSo far, a TCP session is successfully completed. The next blog will discuss the status transfer in a TCP session and analyze some packet capture results different from those in this article.
TCP echo server/client Analysis