Linux网络编程之tcpdump抓包分析TCP三次握手过程

2023-05-16

        使用TCP协议进行网络通讯时,通信的两端首先需要建立起一条连接链路,当然这并不表示使用UDP通信不需要“连接链路”,这里说的连接链路指的是通信协议范畴的东东,并不是物理介质或者电磁波信号,只所以说TCP是面向连接的网络通信协议,主要是指双方在通信时都会保持一些连接相关的信息,比如已收到的分组的序列号,下一次需要收到的分组的序号,对方的滑动窗口信息等等。

        OK,闲话少扯,我们进入主题,下面结合一个简单的TCP服务端与客户端代码,借助tcpdump命令来分析一下TCP建立连接时的三次握手过程(Three-way handshake process)。

服务端代码如下:

/**
 * server.c
 *
 * TCP server program, it is a simple example only.
 *
 * Writen By: Zhou Jianchun
 * Date: 2011.08.12
 *
 * Compiled With: gcc -o client client.c
 * Tested On: Ubuntu 11.04 LTS
 *
 * gcc version: 4.5.2
 *
 */

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <time.h>
#include <strings.h>
#include <string.h>

#define SERVER_PORT 20000
#define LENGTH_OF_LISTEN_QUEUE 10
#define BUFFER_SIZE 255
#define WELCOME_MESSAGE "welcome to our server."

int main(int argc, char **argv)
{
	int server_fd, client_fd;
	struct sockaddr_in server_addr, client_addr;

	if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		printf("create socket error, exit!\n");
		exit(1);
	}

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);
	server_addr.sin_addr.s_addr = htons(INADDR_ANY);

	if(bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
	{
		printf("bind to port %d failed, exit!\n", SERVER_PORT);
		exit(1);
	}

	if(listen(server_fd, LENGTH_OF_LISTEN_QUEUE) < 0)
	{
		printf("failed to listen, exit!\n");
		exit(1);
	}

	while(1)
	{
		char buf[BUFFER_SIZE];
		long timestamp;
		socklen_t length = sizeof(client_addr);
		client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &length);
		if(client_fd <0)
		{
			printf("call accept error, break from while loop!\n");
			break;
		}
		strcpy(buf, WELCOME_MESSAGE);
		printf("connect from client: IP: %s, Port: %d\n", (char *)inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
		timestamp = time(NULL);
		strcat(buf, "timestamp on server:");
		strcat(buf, ctime(×tamp));
		send(client_fd, buf, BUFFER_SIZE, 0);
		close(client_fd);

		close(server_fd);
		return 0;
	}
}

客户端代码:

/**
 * client.c
 *
 * TCP client program, it is a simple example only.
 *
 * Writen By: Zhou Jianchun
 * Date: 2011.08.12
 *
 * Compiled With: gcc -o client client.c
 * Tested On: Ubuntu 11.04 LTS
 *
 * gcc version: 4.5.2
 *
 */

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

#define SERVER_PORT 20000
#define CLIENT_PORT ((20001 + rand()) % 65536)
#define BUFFER_SIZE 255
#define REQUEST_MESSAGE "welcome to connect the server.\n"

void usage(char *name)
{
	printf("usage: %s IP\n", name);
}
int main(int argc, char **argv)
{
	int server_fd, client_fd, length = 0;
	struct sockaddr_in server_addr, client_addr;
	socklen_t socklen = sizeof(server_addr);
	char buf[BUFFER_SIZE];

	if(argc < 2)
	{
		usage(argv[0]);
		exit(1);
	}
	if((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		printf("create socket error, exit!\n");
		exit(1);
	}
	srand(time(NULL));
	bzero(&client_addr, sizeof(client_addr));
	client_addr.sin_family = AF_INET;
	//client_addr.sin_port = htons(CLIENT_PORT);
	client_addr.sin_port = htons(40000);
	client_addr.sin_addr.s_addr = htons(INADDR_ANY);

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	inet_aton(argv[1], &server_addr.sin_addr);
	server_addr.sin_port = htons(SERVER_PORT);

	/*if(bind(client_fd, (struct sockaddr*)&client_addr, sizeof(client_addr)) < 0)
	{
		printf("bind to port %d failed, exit!\n", CLIENT_PORT);
		exit(1);
	}*/

	if(connect(client_fd, (struct sockaddr*)&server_addr, socklen) < 0)
	{
		printf("can not connect to %s, exit!\n", argv[1]);
		exit(1);
	}

	/*length = recv(client_fd, buf, BUFFER_SIZE, 0);
	if(length < 0)
	{
		printf("recieve data from %s error, exit!\n", argv[1]);
		exit(1);
	}
	*/
	char *tmp = buf;
	while((length = read(client_fd, tmp, BUFFER_SIZE)) > 0)
	{
		tmp += length;
	}
	printf("frome server %s:\n\t%s", argv[1], buf);
	close(client_fd);
	return 0;
}

代码逻辑十分简单,服务端程序启动后监听在20000端口,等待外部连接,客户端启动后连接过来,服务端发送一串字符串信息给客户端,然后退出,客户端在读取完信息后也退出。

运行程序之前先在另一个终端下输入如下命令:

tcpdump 'port 20000' -i lo -S

待两端程序退出后可以看到该命令输出如下信息:

17:05:35.358403 IP neptune.local.49493 > neptune.local.20000: Flags [S], seq 1317094743, win 32792, options [mss 16396,sackOK,TS val 7083694 ecr 0,nop,wscale 6], length 0
17:05:35.358439 IP neptune.local.20000 > neptune.local.49493: Flags [S.], seq 1311370954, ack 1317094744, win 32768, options [mss 16396,sackOK,TS val 7083694 ecr 7083694,nop,wscale 6], length 0
17:05:35.358468 IP neptune.local.49493 > neptune.local.20000: Flags [.], ack 1311370955, win 513, options [nop,nop,TS val 7083694 ecr 7083694], length 0
17:05:35.358871 IP neptune.local.20000 > neptune.local.49493: Flags [P.], seq 1311370955:1311371210, ack 1317094744, win 512, options [nop,nop,TS val 7083694 ecr 7083694], length 255
17:05:35.358890 IP neptune.local.49493 > neptune.local.20000: Flags [.], ack 1311371210, win 530, options [nop,nop,TS val 7083694 ecr 7083694], length 0
17:05:35.358913 IP neptune.local.20000 > neptune.local.49493: Flags [F.], seq 1311371210, ack 1317094744, win 512, options [nop,nop,TS val 7083694 ecr 7083694], length 0
17:05:35.359419 IP neptune.local.49493 > neptune.local.20000: Flags [F.], seq 1317094744, ack 1311371211, win 530, options [nop,nop,TS val 7083694 ecr 7083694], length 0
17:05:35.359441 IP neptune.local.20000 > neptune.local.49493: Flags [.], ack 1317094745, win 512, options [nop,nop,TS val 7083694 ecr 7083694], length 0

下面我们逐条进行分析:

1.客户端通过49493端口向服务端的20000端口发送一个SYN同步请求包,展开第一次握手,其中Flags [S]表求数据包的类型为SYN, 即同步请求包,seq字段标识数据包序列号。

2.服务端发送ACK确认包,同时附代一个SYN请求包,在确认客户端同步请求的同时向客户端发送同步请求,其中Flags [S.]中的点号表示这是个确认包(ACK),S表示它同时又是一个SYN请求包。因为TCP是双工通信协议,连接建立之后双方可以同时收发数据,所以双方都发送了SYN包请求同步。

3.客户端发送ACK包确认服务端的SYN同步请求,可以看到此时Flags中只有一个小数点,表示这个包只是用来做确认的。

到此为止,三次握手过程就结束了,双方如果都收到了ACK包,则都进入到ESTABLISHED状态,表明此时可以进行数据发送了。

4.服务端向客户端发送一个数据包,包中的内容就是一个字符串,可以看到此时的Flags标识中有个字母P,意为PUSH DATA,就是发送数据的意思。

至此TCP三次握手过程的分析就结束了,由于本人水平有限,博客中的不妥或错误之处在所难免,殷切希望读者批评指正。同时也欢迎读者共同探讨相关的内容,如果乐意交流的话请留下您宝贵的意见,谢谢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux网络编程之tcpdump抓包分析TCP三次握手过程 的相关文章

  • 为PX4添加串口通讯模块(模块结构)

    主要讲模块的结构 不贴代码 从最外层开始 执行read uart main start dev ttyS1 read uart main int argc char argv 入口函数 判断任务进程read uart task是否存在 根据
  • C++抽象基类与虚基类(C++ primer)

    c 43 43 primer plus P508 xff0c 抽象基类 c 43 43 primer plus P556 xff0c 虚基类 抽象基类 xff08 abstract base class xff0c ABC xff09 抽象
  • MFC学习笔记(二)处理命令行选项

    目标 让应用程序处理这里所见的命令行标志 gt XXX exe c d 策略 一个MFC应用程序可以用CCommandLineInfo类的成员函数ParseParam 处理一些标准标 志 要添加我们自己的标志 xff0c 而仍然能够支持另外
  • C++ expection异常类、捕获所有异常(C++ primer,P639)

    expection类 头文件 lt expection gt stdexcept类 C 43 43 primer plus xff0c P632 包含以下异常 xff1a domain errorinvalid argumentlength
  • 5.1 运输层协议

    运输层协议 运输层的复用与常见端口常用端口 UDP协议特点UDP帧格式 TCP协议特点socket套接字可靠传输工作原理TCP帧首部重要字段 TCP可靠传输以字节为单位的滑动窗口选择超时重传时间选择确认SACK xff08 未经常使用P22
  • Linux上VScode + cmake + gcc开发环境搭建

    VScode 43 cmake 43 gcc 下载 安装vscode安装插件cmake文件结构vscode修改json文件编译 调试的过程 下载 安装 span class token comment cmake gcc 安装都很简单 sp
  • 软件测试面试04:实战项目介绍

    4 1 简单介绍下最近做过的项目 根据自己的项目整理完成 xff0c 要点 xff1a 1 xff09 项目背景 业务 需求 核心业务的流程 2 xff09 项目架构 xff0c B S还是C 5 xff0c 数据库用的什么 中间件用的什么
  • 一张图搞定SDF的概念

    本文仅代表个人理解 xff0c 谬误之处请指正 SDF Signed Distance Field 译为有向距离场 xff0c 有向 距离 场 这三个词非常精确的描述了 sdf 究竟是个什么东西 GPU Gems 3 中是这么描述 sdf
  • Ubuntu Windows双系统切换最简方法!!!

    安装完Ubuntu windows双系统后的第一个问题 xff1a 该怎么在两个系统间快速自由切换呢 xff1f 本文给出两种无需命令行的实用易上手方式 一 什么 xff0c 你要快快快快速切换 xff1f 这里直接给出答案 xff0c F
  • C++primer(第五版)习题答案

    前两章习题较简单 xff0c 这里就不作整理了 xff0c 直接从第三章开始 持续更新 xff1a Chapter 3 Strings Vectors and Arrays Exercise 3 1 part 1 include lt io
  • PX4源码地址和wiki

    源码 https github com 987419640 Firmware wiki https dev px4 io v1 9 0 zh concept architecture html
  • 视觉十四讲:第七讲_2D-2D:对极几何估计姿态

    1 对极几何 从2张图片中 得到若干个配对好的2d特征点 就可以运用对极几何来恢复出两帧之间的运动 设P的空间坐标为 P 61 X Y Z T 两个像素点 p 1 p 2 的像素坐标为 s 1 p 1 61 KP s 2 p 2 61 K
  • VINS_FUSION入门系列---GPS与VIO融合

    参考的博客 https blog csdn net subiluo article details 105429471 http www luyixian cn news show 313718 aspx state 状态量 位姿 速度 b
  • 几种常用加壳软件图文详解

    为了保护自己的软件不轻易被他人 借鉴 xff0c 有必要对软件进行一些加密保护 xff0c 而这方面目前己有成熟的专业加密软件可选择 但不要太依赖壳的保护 xff0c 大多数壳是可以被攻破的 xff0c 还是在自身保护上下些功夫 加密软件比
  • debian添加source源后update出现GPG错误

    错误如下 xff1a W GPG error http mirrors 163 com debian buster updates InRelease The following signatures couldn 39 t be veri
  • windows clang 编译Qt

    准备 xff1a qt everywhere src 5 15 0 zip jom 1 1 3 zip LLVM 10 0 0 win64 exe VS2019 xff1a 需要安装win10 SDK xff0c 也有自带的clang xf
  • docker 最新Dockerfile命令手册

    Dockerfile Reference Docker can build images automatically by reading the instructions from a Dockerfile A Dockerfile is
  • 单片机移植 - RTOS总结 -uC/OS-II ; FreeRTOS的区别

    RTOS总结 uC OS II FreeRTOS的区别 实时操作 xff08 RTOS xff09 系统有很多种 xff0c 分别为 Clinux C OS II eCos FreeRTOS mbed OS RTX Vxworks QNX
  • CentOs Stream脚本安装单机版Kubernetes并配置Calico和NFS

    随着Kubernetes和CentOs的不断升级 xff0c 在安装Kubernetes时 xff0c 网上其他的一些参考资料可能会遇到一些问题 本文以脚本方式列出了所有步骤 xff0c 这些步骤对于一台纯净的CentOs Stream服务
  • java基础必备丨阿里云kubernetes集群部署

    1 创建的前提 开通资源编排服务ROS 因为阿里云的k8s集群依赖于ROS的资源编排 xff0c 所以 xff0c 要先开通ROS才可以创建k8s集群开通弹性伸缩服务ESS开通访问控制服务RAM 2 创建说明 每个账号创建的云资源是由于配额

随机推荐

  • 从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick

    系列文章目录 Github开源地址 从头开始写STM32F103C8T6驱动库 xff08 一 xff09 STM32CubeMX创建并调整工程结构 从头开始写STM32F103C8T6驱动库 xff08 二 xff09 编写系统初始化程序
  • 【ROS】在 Ubuntu 20.04 安装 ROS 的详细教程

    ROS安装指南 目录 ROS安装指南 前言 一 配置Linux清华镜像源1 1 介绍1 2 开始配置 二 安装ROS2 1 ROS的介绍2 1 开始安装 xff1a 配置公钥2 2 系统更新2 3 安装ROS 三 配置ROS3 1 初始化r
  • 京东业务增长10倍背后的敏捷开发秘籍【案例+分析】

    需求又要改 xff1f 项目上线时间又提前了 xff1f 老板还嫌增长不够 xff1f 团队都开始灰心丧气了 xff1f 来看看京东内部是如何解决这些让人焦头烂额的棘手问题 1 两次失败之后成功支持双11活动 京东每年两次大的的促销活动中都
  • 串口调试助手源程序

    目次 xff1a 1 建立项目 2 在项目中插入MSComm控件 3 利用ClassWizard定义CMSComm类控制变量 4 在对话框中添加控件 5 添加串口事件消息处理函数OnComm 6 打开和设置串口参数 7 发送数据 8 发送十
  • 【统计计算之非均匀分布随机数的生成】

    在学习统计计算这门课中 xff0c 学习到了非常多的算法 xff0c 个人觉得非常有趣 xff0c 希望可以和大家总结分享一下 持续更新中 我们用的课本 xff1a 统计计算 李东风 非均匀分布随机数 1 变换法 变换法主要分为两种 xff
  • Ubuntu 18.04在 VMware中启动时一直停留在Starting Update UTMP about System Runlevel Changes

    环境 Ubuntu 18 04 安装在VMware中 问题 启动时一直停留在Starting Update UTMP about System Runlevel Changes 解决思路 由于本人的虚拟机磁盘空间所剩无几 xff0c 怀疑是
  • linux零碎知识点

    源码包安装的 Apache 默认伪用户 xff1a daemonTCP IP是一个工业标准而非国际标准TCP IP可以用于同一主机上不同进程之间的通信Linux 由 Kernel Shelll 应用程序 组成网络协议三要素 xff1a 语义
  • 算法小知识

    一个数如果恰好等于它的因子之和 xff0c 这个数就称为 完数 例如6 61 1 xff0b 2 xff0b 3 xff0c 再如8的因子和是7 xff08 即1 43 2 43 4 xff09 xff0c 8不是完数回文数是指正序 xff
  • 启动 tomcat ,一直停在com.alibaba.druid.pool.DruidDataSource:init

    启动 tomcat 一直停在com alibaba druid pool DruidDataSource init clean一下就可以了
  • Win10 触摸屏 快捷键操作

    Win10 触摸板 快捷键操作 在 Windows 10 笔记本电脑的触摸板上试用这些手势 xff1a 快捷键 选择项目 xff1a 点击触摸板右键单击效果 xff1a 两根手指点击一次应用滚动 xff1a 将两个手指放在触摸板上 xff0
  • JCE cannot authenticate the provider BC

    JCE cannot authenticate the provider BC 解决办法 xff1a 修改 JAVA HOME jre lib security java security 文件 添加如下内容 security provid
  • Docker命令之:load命令

    作用 xff1a Load span class hljs operator an span image span class hljs built in from span span class hljs operator a span
  • Docker命令之: tag命令

    作用 xff1a span class hljs operator span class hljs keyword Create span a tag TARGET IMAGE that refers span class hljs key
  • installshield中增加BDE组件

    在C Program Files Common Files Borland Shared BDE下面有一个bdeinst cab xff0c 把它解压开后有一个bdeinst dll xff0c 把他打包到你的安装程序 xff0c 然后选择
  • intellij idea 合并分支到主分支,主分支代码同步到某一分支

    将gith或者Gitee上的项目clone到本地 git span class hljs keyword clone span https span class hljs comment xxxx span 打开intellij idea
  • springboot项目 intellij idea 找不到或者无法加载主类

    试了很多种网上的方法 xff0c 例如清除缓存 xff0c 指定module path 重启等都没有起作用 最后发现是 project structure project settings project project compiler
  • Vivado综合running时间太长

    cancel后查看log日志 xff0c 出现警告warnning PID not specified xff0c 解决办法 xff1a 新建一个工程 xff0c 导入原工程源文件 xff0c 重新进行综合 xff0c 就可以了
  • 使用putty和ssh登录时进不去

    我的是win10系统 初步理解ssh是一个协议 xff0c putty是一个使用这个协议连接本地电脑和远程服务器的开源软件 我知道连接ssh有两种方式 xff1a 第一种 xff1a 电脑左下角搜索界面输入 terminal 打开命令行cm
  • 联想win10安全模式进入以及退出

    进入安全模式的办法 xff1a 1 按住shift再点击重启 疑难解答 可进入带命令提示符的安全模式 进去后仅命令行一个窗口 xff0c 关闭后会出现黑屏 xff0c 仅有一个光标 2 桌面运行win 43 r 勾选安全引导 可直接进入安全
  • Linux网络编程之tcpdump抓包分析TCP三次握手过程

    使用TCP协议进行网络通讯时 xff0c 通信的两端首先需要建立起一条连接链路 xff0c 当然这并不表示使用UDP通信不需要 连接链路 xff0c 这里说的连接链路指的是通信协议范畴的东东 xff0c 并不是物理介质或者电磁波信号 xff