【网络】TCP协议的相关实验

news2024/11/27 18:30:13

TCP协议的相关实验

  • 一、理解listen的第二个参数
    • 1、实验现象
    • 2、TCP 半连接队列和全连接队列
    • 3、关于listen的第二个参数的一些问题
    • 4、SYN洪水
      • Ⅰ、什么是SYN洪水攻击
      • Ⅱ、如何解决SYN洪水攻击?
  • 二、使用Wireshark分析TCP通信流程

一、理解listen的第二个参数

在编写TCP套接字的服务器代码时,在进行了套接字的创建和绑定之后,需要调用listen函数将创建的套接字设置为监听状态,此后服务器就可以调用accept函数获取建立好的连接了。其中listen函数的第一个参数就是需要设置为监听状态的套接字,而listen的第二个参数我们一般设置为16,32,64,128,可是为什么要设置为这些值呢?listen函数的第二个参数具体的含义是什么呢?下面我们先看代码的实验结果再来说为什么。

1、实验现象

下面的代码通过一个实验来说明listen的第二个参数的具体含义:

  • 先编写TCP套接字的服务器端代码,服务器初始化时依次进行套接字创建、绑定、监听,但服务器初始化后不调用accept函数获取底层建立好的连接。
  • 为了方便验证,这里将listen函数的第二个参数设置为1。
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>

const int port = 8081;
const int num = 1;

int main()
{
	// 1. 创建监听套接字
	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (listen_sock < 0)
    {
		std::cerr << "socket error" << std::endl;
		return 1;
	}
	int opt = 1;
	setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	// 2. 绑定
	struct sockaddr_in local;
	memset(&local, 0, sizeof(local));
	local.sin_port = htons(port);
	local.sin_family = AF_INET;
	local.sin_addr.s_addr = INADDR_ANY;
	
	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
		std::cerr << "bind error" << std::endl;
		return 2;
	}

	// 3. 监听
	if (listen(listen_sock, num) < 0)
    {
		std::cerr << "listen error" << std::endl;
		return 3;
	}
	//启动服务器
	while(true)
    {
		//不调用accept获取连接
        sleep(1);
	}
	return 0;
}

运行服务器后使用netstat -natp | grep 进程名命令,可以看到该服务器当前正处于监听状态。

在这里插入图片描述

接下来新建三个会话,在三个会话中我们都使用telnet进行连接我们的服务器程序。

在这里插入图片描述

然后此时我们使用netstat -natp | head -2 && netstat -natp | grep 8081进行查看连接状态。

在这里插入图片描述

我们发现三个telnet客户端连接的状态都是ESTABLISH状态,而对于服务器端,却只有两个ESTABLISH状态和一个SYN_RECV状态。

在这里插入图片描述

  • 对于SYN_RECV的状态,也就意味着服务器没有收到客户端的ACK,但是这里并不是这样的(丢包的概率是很小的),对刚才客户端发来的ACK,服务器即使收到了但是服务器不能让自己进入ESTABLISH状态(原因后面说)。

  • 然后你后面使用更多的客户端连接服务器你会发现只有两个客户端能和服务器建立正常的连接,其他的都会让服务器处于SYN_RCVD状态,而这个状态不稳定,如果一直无法进行三次握手,就会直接放弃建立连接。

2、TCP 半连接队列和全连接队列

实际TCP在进行连接管理时在内核中存在两个连接队列:

  • 全连接队列(accept队列),全连接队列用于保存已经处于ESTABLISHED状态,但没有被上层调用accept取走的连接。
  • 半连接队列 (SYN 队列),半连接队列用于保存处于SYN_SENTSYN_RECV状态的连接,也就是还未完成三次握手的连接。

而全连接队列的长度实际会受到listen第二个参数的影响,全连接队列的长度由两个值决定:

  • 用户层调用listen时传入的第二个参数backlog
  • 系统变量net.core.somaxconn,默认值为128

真实的全连接队列的长度等于listen传入的backlog和系统变量net.core.somaxconn中的较小值加1

通过以下命令可以查看系统变量net.core.somaxconn的值。

sudo sysctl -a | grep net.core.somaxconn

在这里插入图片描述

因为我们实验时设置listen第二个参数的值为1,此时在服务器端全连接队列的长度就为2,因此服务器最多只允许有两个处于ESTABLISHED状态的连接。

所以第三个客户端发来建立连接请求时,此时服务器端就会新增状态为SYN_RECV的状态,于是放入半连接队列当中,即使服务端收到了客户端的ACK响应,但是全连接队列已经满了,于是第三个连接就没有办法进入全连接队列,于是一直处于SYN_RECV状态。


linux中可以使用 ss 命令,来查看 TCP 全连接队列的情况:

但需要注意的是 ss 命令获取的 Recv-Q/Send-Q 在「LISTEN 状态」和「非 LISTEN 状态」所表达的含义是不同的。

  • l 显示正在监听 ( listening ) 的 socket
  • n 不解析服务名称
  • t 只显示 tcp socket

在「LISTEN 状态」时,Recv-Q/Send-Q 表示的含义如下:
在这里插入图片描述

  • Recv-Q:当前全连接队列的大小,也就是当前已完成三次握手并等待服务端 accept() 的 TCP 连接;
  • Send-Q:值等于listen的第二个参数,表示当前全连接最大队列长度 - 1,上面的输出结果说明监听 8081 端口的 TCP 服务,最大全连接长度为 2;

在「非 LISTEN 状态」时,Recv-Q/Send-Q 表示的含义如下:

在这里插入图片描述

  • Recv-Q:已收到但未被应用进程读取的字节数;
  • Send-Q:已发送但未收到确认的字节数;

3、关于listen的第二个参数的一些问题

1. 问:不考虑其他参数,是不是listen的第二个参数为多少,服务器就可以同时处理几个连接?

答案是:不是,我们这个实验中我们没有使用accept函数,于是导致了建立的连接无法从全连接队列中取走,如果我们使用了accept函数连接被取走,服务器就可以对连接进行处理,全连接队列里面有连接进入,有连接被取走,服务器可以同时对所有已经取走的连接进行处理。

所以这个全连接队列本质是一个缓冲区,用来存放操作系统暂时没有办法处理的连接,这个模型本质也是一个生产者消费者模型。

  • 生产者:半连接队列
  • 消费者:操作系统
  • 缓冲区:全连接队列

2. 问:为什么底层要维护连接队列?

一般当服务器压力较大时连接队列的作用才会体现出来,如果服务器压力本身就不大,那么一旦底层有连接建立成功,上层就会立马将该连接读走并进行处理。

服务器端启动时一般会预先创建多个服务线程为客户端提供服务,主线程从底层accept上来连接后就可以将其交给这些服务线程进行处理:

  • 如果向服务器发起连接请求的客户端很少,那么连接一旦在底层建立好就被主线程立马accept上来并交给服务线程处理了。

  • 但如果向服务器发起连接请求的客户端非常多,当每个服务线程都在为某个连接提供服务时,底层再建立好连接主线程就不能获取上来了,此时底层这些已经建立好的连接就会被放到全连接队列当中,只有等某个服务线程空闲时,主线程就会从这个全连接队列当中获取建立好的连接。

  • 如果没有这个连接队列,那么当服务器端的服务线程都在提供服务时,其他客户端发来的连接请求就会直接被拒绝,但有可能正当这个连接请求被拒绝时,某个服务线程提供服务完毕,此时这个服务线程就无法立马得到一个连接为之提供服务,所以一定有一段时间内这个服务线程是处于闲置状态的,直到再有客户端发来连接请求。

而如果设置了连接队列,当某个服务线程提供完服务后,如果连接队列当中有建立好的连接,那么主线程就可以立马从连接队列当中获取一个连接交给该服务线程进行处理,此时就可以保证服务器几乎是满载工作的。

3. 问:为什么连接队列既不能太长?

虽然维护连接队列能让服务器处于几乎满载工作的状态,但连接队列也不能设置得太长。

  • 第一:服务器维护连接也是需要成本的,连接队列设置的越长,系统就要花费越多的成本去维护这个队列。
  • 第二:如果队列太长,也就意味着在队列较尾部的连接需要等待较长时间才能得到服务,此时客户端的请求也就迟迟得不到响应。此外,与其维护一个很长的连接占用大量暂时用不到的资源,造成客户端等待过久,还不如将部分资源节省出来给服务器使用,让服务器更快的为客户端提供服务。

4、SYN洪水

Ⅰ、什么是SYN洪水攻击

我们都知道 TCP 连接建立是需要三次握手,假设攻击者用大量的假IP地址发送初始连接请求(SYN)数据包,让服务端建立连接,然后切换IP继续发,服务端每接收到一个 SYN 报文,就进入SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的半连接队列,使得服务端不能为正常用户服务。

SYN 攻击方式最直接的表现就会把 TCP 半连接队列打满,这样当 TCP 半连接队列满了,后续再在收到 SYN 报文就会丢弃,导致客户端无法和服务端建立连接。

Ⅱ、如何解决SYN洪水攻击?

首先这一定是一个综合性的解决方案,TCP作为传输控制协议需要对其进行处理,而上层应用层也要尽量避免遭到SYN洪水攻击。

在应用层

  • 比如应用层可以记录向服务器发起连接建立请求的主机信息,如果发现某个主机多次向服务器发起SYN请求,但从不对服务器的SYN+ACK进行ACK响应,此时就可以对该主机进行黑名单认证,此后该主机发来的SYN请求一概不进行处理。

在传输层

现在核心的问题就是半连接队列被占满了,但不能简单的扩大半连接队列,就算半连接队列再大,恶意用户也能发送更多的SYN请求来占满,并且维护半连接队列当中的连接也是需要成本的。

于是TCP为了防范SYN洪水攻击,引入了syncookie机制:

开启 syncookies 功能就可以在不使用 SYN 半连接队列的情况下成功建立连接,相当于绕过了 SYN 半连接来建立连接

syncookie的工作机制如下:

  • 当服务器收到一个SYN请求时,它会生成一个加密的SYN cookie,该cookie包含了客户端的IP地址、端口号和服务器使用的一些其他信息,并将cookie 值放到第二次握手报文的「序列号」里,然后服务端回第二次握手给客户端;

  • 服务器不会保存任何关于该SYN连接的状态,即该链接不会进入半连接队列中,但是服务器会保存cookie的值。

  • 客户端收到SYN + ACK应答后,会解析其中的SYN cookie,并将其存储起来。

  • 客户端发送带有解析出的SYN cookie的ACK应答给服务器。

  • 服务器接收到ACK应答后,会验证ACK中的SYN cookie是否有效。如果有效,服务器会根据SYN cookie中的信息创建连接(进入全连接队列)并提供服务。

可以看到,当开启了 tcp_syncookies 了,即使受到 SYN 攻击而导致半队列满时,也能保证正常的连接成功建立。

通过使用syncookie机制,服务器可以避免存储大量未完成的连接状态,从而抵御SYN洪水攻击。这种机制的优势是能够快速且有效地处理大量的SYN请求,并且不需要为每个半连接维护状态信息,减少了服务器的负担。

net.ipv4.tcp_syncookies 参数主要有以下三个值:

  • 0 值,表示关闭该功能;
  • 1 值,表示仅当 SYN 半连接队列放不下时,再启用它;
  • 2 值,表示无条件开启功能;

那么在应对 SYN 攻击时,只需要设置为 1 即可。

在这里插入图片描述

在这里插入图片描述

二、使用Wireshark分析TCP通信流程

wireshark是 windows 下的一个网络抓包工具. 虽然 Linux 命令行中有 tcpdump 工具同样能完成抓包,但是 tcpdump 是纯命令行界面,使用起来不如 wireshark 方便。

下载 wireshark

  1. 打开wireshark 2.6.5,主界面如下,选择对应的网卡(这里我们选择WLAN),点击即可进行捕获该网络信息,开始抓取网络包。
    在这里插入图片描述

  2. 在使用Wireshark时可以通过设置过滤器,来抓取满足要求的数据包。


针对IP进行过滤

  • 抓取指定源地址的包:ip.src == 源IP地址
  • 抓取指定目的地址的包:ip.dst == 目的IP地址
  • 抓取源或目的地址满足要求的包:ip.addr == IP地址等价于ip.src ==源IP地址 or ip.dst == 目的IP地址
  • 抓取除指定IP地址之外的包:!(表达式)

针对协议进行过滤

  • 抓取指定协议的包:协议名(只能小写)
  • 抓取多种指定协议的包:协议名1 or协议名2
  • 抓取除指定协议之外的包:not 协议名 或 !协议名

针对端口进行过滤(以TCP协议为例):

  • 抓取指定端口的包:tcp.port == 端口号
  • 抓取多个指定端口的包:tcp.port >= 2048(抓取端口号高于2048的包)。

针对长度和内容进行过滤

  • 抓取指定长度的包:udp.length < 30 http.content_length <= 20
  • 抓取指定内容的包:http.request.urimatches "指定内容"

这里我们抓取指定源IP地址或目的IP地址的数据包,选择完毕记得按回车。

在这里插入图片描述

  1. 在windows 的CMD使用 telnet 作为客户端连接上服务器 telnet [ip] [port]

在这里插入图片描述

  1. 当我们用telnet命令连接该服务器后,就可以抓取到三次握手时双方交互的数据包。

在这里插入图片描述

在这里插入图片描述

  1. 而当我们退出telnet连接后,就可以抓取到四次挥手时双方交互的数据包。(此处四次挥手时进行了捎带应答,第二次挥手和第三次挥手合并在了一起,第二个包不是TCP数据包,是SSH数据包)
    在这里插入图片描述

在 TCP 挥手过程中,「没有数据要发送」并且「开启了 TCP 延迟确认机制」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1218843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【23真题】无耻!“官方”假真题!害人!

这套华侨23真题是学弟给我从考场抄出来的版本&#xff0c;我刚刚做完解析&#xff01;后台就收到了另外一份“官方华侨23真题”的投稿。我本想对对回忆版&#xff0c;补充下题干。结果一对吓一跳&#xff01;竟然一道题都不一样&#xff01;给大家看下&#xff0c;真的好逼真&a…

《向量数据库指南》——TruLens + Milvus Cloud 构建RAG案例

具体案例 如前所述,RAG 配置选择可能对消除幻觉产生重大影响。下文中将基于城市百科文章构建问答 RAG 应用并展示不同的配置选择是如何影响应用性能的。在搭建过程中,我们使用 LlamaIndex 作为该应用的框架。大家可以在 Google Colab( https://colab.research.google.com/git…

Theory behind GAN

假如要生成一些人脸图&#xff0c;实际上就是想要找到一个分布&#xff0c;从这个分布内sample出来的图片像是人脸&#xff0c;分布之外生成的就不像人脸。而GAN要做的就是找到这个distribution。 在GAN之前用的是Maximum Likelihood Estimation。 Maximum Likelihood Estimat…

【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏2(附项目源码)

文章目录 先看本次实现的最终效果前言敌人生命值扣血测试&#xff0c;敌人死亡控制敌人动画敌人死亡动画敌人转向问题源码完结 先看本次实现的最终效果 前言 本期紧接着上一篇&#xff0c;本期主要内容是实现敌人血条、动画和行为逻辑。 敌人生命值 绘制血条UI 新建 publ…

快速入门:构建您的第一个 .NET Aspire 应用程序

##前言 云原生应用程序通常需要连接到各种服务&#xff0c;例如数据库、存储和缓存解决方案、消息传递提供商或其他 Web 服务。.NET Aspire 旨在简化这些类型服务之间的连接和配置。在本快速入门中&#xff0c;您将了解如何创建 .NET Aspire Starter 应用程序模板解决方案。 …

unity 烘焙的时候出现模型没有光影的情况

unity 烘焙的时候出现模型没有光影的情况 1.模型没有设置生成光照贴图 需要勾选模型的生成光照贴图UVs,然后应用 2.游戏对象没有勾选静态选项 点开静态下拉列表&#xff0c;选择 contribute GI

Accelerate 0.24.0文档 四:Megatron-LM

参考《Megatron-LM》 文章目录 一、Megatron-LM集成简介二、环境配置设置conda环境的步骤&#xff1a; 二、Accelerate Megatron-LM Plugin三、自定义训练过程四、检查点转换五、文本生成六、支持ROPE 、 ALiBi和Multi-Query Attention七、注意事项 一、Megatron-LM集成简介 在…

再谈谷歌GMS认证之Android 13

写在前面的话 2023年来到一个新的公司&#xff0c;传说中的做互联网金融即将上市的高大上公司。 入职后才发现就是做pos机设备的一个小厂 哎&#xff0c;什么命啊&#xff01; 工作和手机开发的工作重合度可以达到95%以上&#xff0c;我不想做手机&#xff0c;偏偏又干上…

全网首位数字军人“穆兰”惊艳亮相,与拓世法宝共同绘就未来社会图景

古有穆桂英、花木兰挂帅出征&#xff0c;今有全网首位虚拟数字军人“穆兰”展巾帼风采。今年国庆节后&#xff0c;中国军号在全网为解放军新闻传播中心数字记者暨全军首位超写实虚拟数字军人征名&#xff0c;历时一个多月&#xff0c;经过征名提交、评委初评、公众投票、专家共…

验证码识别之OCR识别

验证码识别&#xff1a; 背景&#xff1a; ​ 决定开一个专题给大家讲一下验证码识别&#xff0c;不要多想&#xff0c;我们不搞深度学习&#xff0c;知识用于攻破模拟登录的时候弹出的验证码&#xff0c;后续会给大家讲讲滑块等等&#xff0c;反爬虫策略如何应对。 好了&am…

如何实现业务系统的单点退出

当前我国各领域正在加速向数字化、移动化、智能化发展&#xff0c;大力投入信息化建设与数字化转型已成为企业的共识&#xff0c;但对于很多企业而言&#xff0c;组织信息环境庞大复杂&#xff0c;业务场景变化频繁&#xff0c;给身份管理与信息安全管理带来很大挑战。随着信息…

Spring Bean的生命周期详细梳理

1. 理解Bean的生命周期 1.1 生命周期的各个阶段 在Spring IOC容器中&#xff0c;Bean的生命周期大致如下&#xff1a; 实例化&#xff1a;当启动Spring应用时&#xff0c;IOC容器就会为在配置文件中声明的每个<bean>创建一个实例。属性赋值&#xff1a;实例化后&#…

linux虚拟机环境快速搭建redis5.x版本的主从集群总结

原创/朱季谦 我在阿里云服务器上曾参与过公司redis集群的搭建&#xff0c;但时间久了&#xff0c;都快忘记当时的搭建过程了&#xff0c;故而决定在虚拟机centOS 7的环境&#xff0c;自行搭建一套redis5.x版本的集群&#xff0c;该版本集群的搭建比较方便&#xff0c;不用再像…

免费图像压缩工具分享:15 个最佳免费图像压缩工具

您想在将图像上传到网上之前对其进行压缩吗&#xff1f;优化摄影网站的图像将有助于您的网站加载速度更快。而且&#xff0c;更快的加载速度意味着更好的搜索引擎排名&#xff01;在本指南中&#xff0c;我们将分享用于图像压缩的最佳免费图像优化工具。 许多照片编辑程序&…

【网络奇遇记】我和因特网的初相遇3 —— 计算机网络体系结构

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. 常见的三种计算机网络体系结构1.1 开放系统互连参考模型1.2 TCP/IP参考模型1.3 原理参考模型 二…

电脑上明明保存了文件却不见了?4个恢复技巧分享!

“真的很奇怪&#xff0c;我有一些重要的文件明明保存在电脑上了&#xff0c;但是当我在电脑上查找它们时&#xff0c;却发现有很多文件都不见了。这些保存在电脑上的文件如果不见了怎么找回呢&#xff1f;” 在使用电脑过程中&#xff0c;有时我们会遇到明明保存了文件&#x…

【双向链表】带头双向循环(1)

目录 链表的分类 Test.c主函数 test1头插 test2头删 test3尾插 test4尾删 test5查询 test6插入pos位置后一个 test7删除pos Test.c总代码 DList.h头文件&函数声明 头文件 函数声明 DList.h总代码 DList.c函数实现 Createnode创建节点 LTInit初始化 LTPr…

1~2亿条数据需要缓存之安装redis集群(哈希取余分区、一致性哈希算法分区、哈希槽分区)

安装redis集群 面试题 1~2亿条数据需要缓存&#xff0c;请问如何设计这个存储案例??? 回答: 单机单台100%不可能&#xff0c;肯定是分布式存储&#xff0c;用redis如何落地&#xff1f; 上述问题阿里P6~P7工程案例和场景设计类必考题目&#xff0c; 一般业界有3种解决方案 …

STM32H743 RTC精密数字校准 深度剖析

一、问题 项目中数据报文收到的RTC时间总是会慢一些,经过实际几天的测试得出结论:24小时要慢5S左右。根据手册我了解到可以有误差但不会差这么多,所以进行了如下分析并解决问题。 二、分析 1.影响RTC准确性的因素罗列 硬件基础误差(也就是待校准部分) …

青岛数字孪生赋能工业制造,加速推进制造业数字化转型

随着企业数字化进程的推进&#xff0c;数字孪生技术逐渐在汽车行业得到广泛应用。5G与数字孪生、工业互联网的融合将加速数字中国、智慧社会建设&#xff0c;加速中国新型工业化进程&#xff0c;为中国经济发展注入新动能。数字孪生、工业物联网、工业互联网等新一代信息通信技…