利用tcpdump监控tcp连接三次握手和关闭四次握手

news/2024/5/17 18:51:02 标签: linux, tcp, 三次握手, 四次握手

学习网络编程最主要的是能理解底层编程细节,一开始看《UNIX网络编程卷1:套接字联网API》的时候搞不懂什么seq、ack到底是什么东西,最近了解了tcpdump的一些用法后感觉两者结合起来还是比较容易理握手过程的。以下就通过tcpdump工具来监控相关内容,并和书本上的流程进行对比介绍,希望对入门的童靴有些帮助吧

服务端代码如下:

#include <sys/socket.h> //socket listen bind                                     
#include <arpa/inet.h> // sockaddr head                                                                                                                                                                   
#include <string.h>  //memset and strlen head                                       
#include <sys/socket.h> //socket listen bind                                        
#include <iostream>                                                                 
#include <time.h>                                                                   
#include <stdio.h>                                                                  
                                                                                    
#define MAXLINE 4096                                                                
#define LISTENQ 1024                                                                
                                                                                    
using namespace std;                                                                
                                                                                    
int main(int argc, char ** argv)                                                    
{                                                                                   
    int listenfd, connfd;                                                           
    socklen_t len;                                                                  
    struct sockaddr_in servaddr, cliaddr;                                           
    char buff[MAXLINE];                                                             
    time_t ticks;                                                                   
    listenfd = socket(AF_INET, SOCK_STREAM, 0);                                     
    memset(&servaddr, 0, sizeof(servaddr));                                         
    servaddr.sin_family = AF_INET;                                                  
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);                                   
    servaddr.sin_port = htons(10000);                                               
                                                                                    
    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));                 
    int ret = listen(listenfd,LISTENQ);                                             
    cout << "go to listen" <<ret<< endl;                                            
    for(; ;)                                                                        
    {                                                                               
        len=sizeof(cliaddr);                                                        
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len);               
        cout << "connfd = " << connfd << inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)) << endl;
        sleep(20);                                                                  
        ticks = time(NULL);                                                         
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));                   
        write(connfd, buff, strlen(buff));                                          
        cout << "write date ok" << endl;                                            
        sleep(20);                                                                  
        close(connfd);                                                              
    } 
    return 0;                                                                    
}    




客户端代码如下:

#include <string.h>                                                                 
#include <netinet/in.h>                                                             
#include <sys/socket.h>                                                             
#include <arpa/inet.h>                                                              
#include <iostream>                                                                 
#include <stdio.h>                                                                  
#include <errno.h>                                                               
                                                                                 
using namespace std;                                                             
                                                                                 
#define MAXLINE     4096    /* max text line length */                           
int main(int argc, char ** argv)                                                 
{                                                                                
    int sockfd, n;                                                               
    char recvline[MAXLINE+1];                                                    
    struct sockaddr_in serveraddr;                                               
    if(argc != 2)                                                                
    {                                                                            
        cout << "para error " << endl;                                           
        return 0;                                                                
    }                                                                            
    if((sockfd=socket(AF_INET, SOCK_STREAM, 0))<0)                               
    {                                                                            
        cout << "socket error" << endl;                                          
        return 0;                                                                
    }                                                                            
    memset(&serveraddr,0, sizeof(serveraddr));                                   
    serveraddr.sin_family = AF_INET;                                             
    serveraddr.sin_port = htons(10000);                                          
    if(inet_pton(AF_INET, argv[1], &serveraddr.sin_addr)<=0)                     
    {                                                                            
        cout << "inet_pton error for " << argv[1] << endl;                       
        return 0;                                                                
    }                                                                            
    int tmp = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    if(tmp <0)                                                                                                                                                                                            
    {                                                                               
        cout << "connect error" << tmp << endl;                                     
        cout << "error info " << errno << endl;                                     
        return 0;                                                                   
    } 
    while((n=read(sockfd, recvline, MAXLINE)) > 0)                               
    {                                                                            
        recvline[n] = 0;                                                         
        if(fputs(recvline, stdout) == EOF)                                       
        {                                                                        
            cout << "fputs error" << endl;                                       
        }                                                                        
    }                                                                            
    close(sockfd);                                                               
    if(n<0)                                                                      
    {                                                                            
        cout << "read error" << endl;                                            
    }                                                                            
    return 1;                                                                    
} 

先在192.168.11.220上运行服务端程序,然后在192.168.11.223上运行客户端程序。同时在两个服务器上以root用户执行tcpdump工具,监控10000端口

tcpdump命令如下:

tcpdump 'port 10000' -i eth0 -S

建立连接时服务端220的监控内容如下:


14:52:19.772673 IP 192.168.11.223.55081 > npsc-220.ndmp: Flags [S], seq 1925249825, win 14600, options [mss 1460,sackOK,TS val 11741993 ecr 0,nop,wscale 6], length 0
14:52:19.772695 IP npsc-220.ndmp > 192.168.11.223.55081: Flags [S.], seq 821610649, ack 1925249826, win 14480, options [mss 1460,sackOK,TS val 20292985 ecr 11741993,nop,wscale 7], length 0
14:52:19.773256 IP 192.168.11.223.55081 > npsc-220.ndmp: Flags [.], ack 821610650, win 229, options [nop,nop,TS val 11741994 ecr 20292985], length 0

下面结合上图和下面三次握手示意图,解释握手细节:

第一行显示客户端192.168.11.223先发送一个seq,1925249825给服务端,对应下面三次握手示意图中的SYN J

第二行显示服务端192.168.11.220(npsc-220)确认第一行的请求:seq 1925249825, ack的值为第一行的seq值+1,即(ack 1925249826),同时发送一个请求序列号821610649。对应下图三次握手中的(SYN K, ACK J+1)

第三行显示客户端192.168.11.223确认服务端的请求序号(第二行中的seq 821610649),对应下图tcp三路握手中的 (ACK K+1)



下图显示了传递一次数据的通信过程


14:52:39.773434 IP npsc-220.ndmp > 192.168.11.223.55081: Flags [P.], seq 821610650:821610676, ack 1925249826, win 114, options [nop,nop,TS val 20312985 ecr 11741994], length 26
14:52:39.774208 IP 192.168.11.223.55081 > npsc-220.ndmp: Flags [.], ack 821610676, win 229, options [nop,nop,TS val 11761994 ecr 20312985], length 0

由于代码中服务端建立连接后直接给客户端发送本地时间的数据给客户端,所以上面第一行中的信息可以看出由npsc-220(服务端)发送数据给客户端192.168.11.223,请求序号为:821610650:821610676 共26个字节,

第二行表示客户端223收到数据后给服务端的发送了一个ack的确认信息


下图显示了断开连接的通信过程(其中客户端代表被动断开的一端,服务端代表主动断开的一端)


14:52:59.773523 IP npsc-220.ndmp > 192.168.11.223.55081: Flags [F.], seq 821610676, ack 1925249826, win 114, options [nop,nop,TS val 20332985 ecr 11761994], length 0
14:52:59.774342 IP 192.168.11.223.55081 > npsc-220.ndmp: Flags [F.], seq 1925249826, ack 821610677, win 229, options [nop,nop,TS val 11781994 ecr 20332985], length 0
14:52:59.774351 IP npsc-220.ndmp > 192.168.11.223.55081: Flags [.], ack 1925249827, win 114, options [nop,nop,TS val 20332986 ecr 11781994], length 0


由于我的程序是由服务端主动关闭连接,所以和下图的四次握手示意图稍微有些差别

第一行显示:服务端(npsc-220)主动发送了一个FIN给客户端192.168.11.223,对应下图的FIN M ,其中M的值为821610676

第二行显示:客户端192.168.11.223确认了服务端的821610676(即下图的ACK M+1, 即ack 821610677),并发送了一个FIN给服务端,对应下图的FIN N 

第三行显示:服务端(npsc-220)确认了客户端的FIN  ack 19252429827,即下图的ACK N+1 ,

下图是断开连接的四次握手示意图





http://www.niftyadmin.cn/n/1629191.html

相关文章

配置安装memcached

centos6.21&#xff0c;下载源码包memcached-1.4.4.tar.gz2&#xff0c;解压安装# tar xf memcached-1.4.4.tar.gz# mkdir /usr/local/memcached# cd memcached-1.4.4# yum groupinstall "Desktop Platform Development" "Development tools"# ./configure…

小Q的歌单 | 小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单

题目描述&#xff1a; 小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌&#xff0c;现在小Q想用这些歌组成一个总长度正好为K的歌单&#xff0c;每首歌最多只能在歌单中出现一次&#xff0c;在不考虑歌单内歌曲的先后顺序的情况下&#xff0c;请问有多少种组成歌单的方法。 输…

【20180409】IT管理之IT十二条令

团队越来越大&#xff0c;靠人管几乎有力无心&#xff0c;只能靠制度管理了。前段时间对部门颁布了12条令&#xff0c;效果明显。特此Mark。汇报&#xff1a;三条总结&#xff1a;汇报讲究精简&#xff0c;一个事情最多一句话概括。一页报告&#xff1a;内容精简&#xff0c;报…

说说安全狗服云的优势与不足

2019独角兽企业重金招聘Python工程师标准>>> 【安全狗服云品酒论剑】我对安全狗服云的深度测评。  服务器被攻击是常有的事&#xff0c;自从上一次被ARP攻击后最先想到的是安全狗&#xff0c;其实除了安全狗貌似还找不到别的软件来管理服务器&#xff0c;尤其是免…

Linux | Linux的文件权限与目录配置

目录 一.使用者与群组 1.文件拥有者 2.群组概念 3.其他人的概念 4.Linux用户身份与群组记录的文件 二.Linux文件权限概念 1.Linux文件属性 三.如何改变文件属性与权限 1.改变所属群组 chgrp 2.改变文件拥有者 chown 3.改变权限 chmod 四.目录与文件之权限意义 1.权…

思科—计算机网络课程设计—第五章交换机配置概念测试

题目1 打开交换机时&#xff0c;启动顺序中的第一个操作是什么&#xff1f; 选择一项&#xff1a; 加载默认 Cisco IOS 软件加载启动加载器软件低级 CPU 初始化加载加电自检程序反馈 Refer to curriculum topic: 5.1.1 交换机启动后的第一个操作是 POST&#xff08;加电自检…

MVC3中在同一解决方案的不同项目中实现Area功能

1、背景微软在MVC中引入了Area概念&#xff0c;用于复杂项目的分工开发。如一个MVC项目中Controller过多时&#xff0c;就会导致项目中包含大量的ControllerViewModel&#xff0c;无论是查找还是调试都比较麻烦。因此微软引入了Area概念&#xff0c;不过默认也是在同一个项目中…

思科—计算机网络课程设计—第六章VLAN概念测试

题目1 请参见图示。路由器 CiscoVille 上 VLAN 间路由配置中显示的错误的原因是什么&#xff1f; 选择一项&#xff1a; gig0/0 接口不支持 VLAN 间路由。no shutdown 命令尚未配置。CiscoVille 上的 IP 地址不正确。encapsulation dot1Q 20 命令尚未配置。反馈 Refer to cur…