zoukankan      html  css  js  c++  java
  • 利用tcpdump分析工具来验证tcp连接的建立和关闭过程

      本文要求读者在阅读之前应该对TCP通过三次握手建立和关闭连接有一定的了解,本文并没有详细讲解三次握手,只是通过一个实例对三次握手进行了一下验证。

      tcp连接的建立和关闭想必大家都已经非常熟悉了!通过三次握手建立连接和通过三次或者四次(半关闭)握手来关闭连接!在这里,我想通过一个具体的实例程序,来分析一下这个过程!

      首先说用到的工具吧,linux下的tcpdump命令,和自己用c语言写的一个服务器端和一个客户端程序。程序的代码如下:

      头文件:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<sys/types.h>
     4 #include<sys/socket.h>
     5 #include<netinet/in.h>
     6 #include<netdb.h>
     7 #include<errno.h>
     8 #include<signal.h>
     9 #include<unistd.h>
    10 #include<string.h>
    11 #include<sys/wait.h>
    12 #include<arpa/inet.h>
    Header

      服务器端:

     1 #include"header.h"
     2 int main(int argc,char *argv[])
     3 {
     4     int socket_n;    //套接字描述符
     5     int listen_s;    //监听套接字描述符
     6     socklen_t cli_addr_len;            //客户端地址长度
     7     struct sockaddr_in server_addr; //服务器地址
     8     struct sockaddr_in client_addr; //客户端地址
     9 
    10     int n=0;        //接受到的数据长度
    11     char buffer[256];    //数据缓冲区
    12     int maxLen=sizeof(buffer);
    13     memset(buffer,0,maxLen);
    14     char cli_addr[20];
    15 
    16     //回创建监听套接字
    17     listen_s=socket(AF_INET,SOCK_STREAM,0);
    18 
    19     //创建本地服务器套接字
    20     memset(&server_addr,0,sizeof(server_addr));
    21     server_addr.sin_family = AF_INET;
    22     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    23     server_addr.sin_port=htons(9877);
    24 
    25     //将套接字绑定到本地套接字地址
    26     if(bind(listen_s,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
    27     {
    28         perror("Error:binding failed!");
    29         exit(0);
    30     }
    31     //监听链接请求
    32     if(listen(listen_s,maxLen) < 0)
    33     {
    34     perror("Error:listening failed!");
    35     exit(1);
    36     }
    37 
    38     while(1)
    39     {
    40     if((socket_n=accept(listen_s,(struct sockaddr *)&client_addr,&cli_addr_len)) < 0)
    41     {
    42         perror("Error:accepting failed!");
    43         exit(1);
    44     }
    45     read(socket_n,buffer,maxLen);
    46     inet_ntop(AF_INET,&client_addr.sin_addr,cli_addr,sizeof(cli_addr));
    47     printf("%s sent %s",cli_addr,buffer);
    48     write(socket_n,buffer,strlen(buffer));
    49     printf("刚刚建立的连接即将关闭
    ");
    50     close(socket_n);
    51     }
    52     return 0;
    53 }
    Server

      客户端:

     1 #include"header.h"
     2 int main(int argc,char *argv[])
     3 {
     4     int sockfd;
     5     char buffer_s[256];
     6     char buffer_r[256];
     7     struct sockaddr_in servaddr;
     8 
     9     memset(buffer_r,0,sizeof(buffer_r));
    10     memset(buffer_s,0,sizeof(buffer_s));
    11 
    12     if(argc != 2)
    13     {
    14     printf("usage : client <IP address>!");
    15     exit(0);
    16     }
    17 
    18     sockfd = socket(AF_INET,SOCK_STREAM,0);
    19     
    20     memset(&servaddr,0,sizeof(servaddr));
    21     servaddr.sin_family = AF_INET;
    22     servaddr.sin_port = htons(9877);
    23     inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
    24 
    25     connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    26 
    27     while(fgets(buffer_s,256,stdin) != NULL)
    28     {
    29     write(sockfd,buffer_s,strlen(buffer_s));
    30     if(read(sockfd,buffer_r,256) == 0)
    31     {
    32         printf("client:server terminated prematurely");   
    33     }
    34     fputs(buffer_r,stdout);
    35     }
    36 
    37     return 0;
    38 }
    Client

      tcpdump用的命令是这句:

    tcpdump -i lo tcp port 9877 and host 127.0.0.1

      这条命令表示,我抓取lo网卡(环回接口)上ip为127.0.0.1且端口号为9877(这个9877是我的程序中服务器绑定的接口)的包!

      运行的结果如下图:

       

      客户端发送一个"a "给服务器,并且接收到一个"a ";

      

      这个截的图有点多了,这个与本文有关的部分就是最底下的从./server 开始的部分,服务器接受到一个"a ",回传给客户端之后立刻将这个连接关闭,并且提示"刚刚建立的连接即将关闭"!

      

      这个是抓包软件抓到的图,这个就得好好分析分析了!

      首先需要说明几点的是,这个分析是从那个15:32:38.348872开始,那个38264表示的是客户端的端口号,9877表示的是服务器的端口号,关于有些包的符号位(图中flags部分)中应该有ACK这个标志,可是具体没有显示,我认为可能是tcpdump省略了,还有些包中的SYN符号(用一个S表示)也可能省略了。另外需要说明的一点是服务器和客户端的序号应该都是随机数,可是连接建立之后就自动从1开始,我认为这个是tcpdump这个软件自动进行了计算!

      第一条信息表示客户端发送给服务器一个包,其序号seq为598232472,标志位为SYN,就是建立连接的第一次握手。客户端发送自己的序号。

      第二条信息表示服务器发送给客户端一个包,其序号seq为3283581888,确认号为5982324272,标志位为SYC(理论上还应该有ACK,可能这里没有显示出来),这就是建立连接的第二次握手,服务器发送这边的序号,并对客户端的序号进行确认。

      第三条信息表示客户端发送给服务器一个包,没有序号,确认号为1(我认为这里是tcpdump这个抓包软件进行了处理),表示想要从服务器接受第一个字节,到这里,三次握手已经完成,客户端到服务器的连接已经建立。

      第四条信息表示客户端发送两个字节的信息给服务器,序号seq为1,确认号为1。标志位为PSH(表示不在窗口里面缓存,直接交给应用程序)。

      第五条信息表示服务器对客户端发送的信息表示确认,确认号为3,没有序号。

      第六条信息表示服务器发送给客户端两个字节的信息,序号为1,确认号为3.符号位为PSH。

      第七条信息表示服务器发送给客户端一个连接终止的FIN信息。序号为3,确认号为3,从这里开始了连接关闭的三次握手过程。(这里是服务器主动关闭的,所以三次握手就变成了二次握手~~)。

      第八条信息表示客户端发送给服务器的一个确认信息,确认号为3,表示对服务器发送的那两个字节的确认。

      第九条信息表示客户端发送一个确认信息给服务器,确认号为4,表示对服务器发送的FIN终止信息进行确认,至此,那个TCP连接也就关闭了。

      OK,这就是三次握手的实例,希望能够帮助大家更好地理解三次握手这个过程。

  • 相关阅读:
    HDU 1800 Flying to the Mars 字典树,STL中的map ,哈希树
    字典树 HDU 1075 What Are You Talking About
    字典树 HDU 1251 统计难题
    最小生成树prim算法 POJ2031
    POJ 1287 Networking 最小生成树
    次小生成树 POJ 2728
    最短路N题Tram SPFA
    poj2236 并查集
    POJ 1611并查集
    Number Sequence
  • 原文地址:https://www.cnblogs.com/bwangel23/p/4149529.html
Copyright © 2011-2022 走看看