标签:style blog http color io os ar 使用 strong
本文将对一个简单的TCP回射服务器和客户端进行抓包,从而分析一次成功而理想TCP会话的基本流程,多次不成功或与预期不一致的抓包结果将在下篇博文进行分析
本文程序编译环境为:
Linux version 3.16.4-1-ARCH
gcc version 4.9.1 20140903 (prerelease)
Glibc 2.18
服务器代码如下:
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 1024 19 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 }
客户端代码如下:
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 1024 19 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 }
首先展示抓包结果,这是一个完全符合书本理论的理想状况,下篇博客将会通过调试器等手段制造非理想状况,进而分析其行为,因此不对TCP包结构进行讨论,TCP包的WIN字段用于滑动窗口的控制,本文暂不涉及
首先:一次TCP会话的基本流程应该分为以下三步
下面即对抓包结果进行分析,从而分析出这三个步骤中实际发生了什么,需要说明的是,抓包得到的No序号和TCP包中seq和ack的序号不是一个东西,由于我使用SSH连接了测试机进行控制,因此抓包软件连同SSH的数据包一并抓取,造成与我们测试内容相关的数据包序号不连续,不过这并不影响我们的分析和理解
22,24,25号数据包即TCP会话基本流程的第一步:与对方套接字建立连接,这个过程一共进行了三次数据包的传递,也就是俗称的三次握手
26,27,28,29四个数据包展示了客户端服务端进行一次数据交换的过程,两个来回,并根据实际的业务逻辑而变化,这就是TCP会话中的第二步:与对方套接字进行数据交换
32,34,36,37号包实现了一次TCP会话中的第三步:断开与对方套接字的连接,这个过程经历了四次数据包的传递,也就是俗称的四次挥手,至此,一次TCP会话成功完成,下篇博文将会讨论一次TCP会话中的状态转移,并分析一些和本文不同的抓包结果
标签:style blog http color io os ar 使用 strong
原文地址:http://www.cnblogs.com/current/p/4051313.html