kernel笔记——网络收发包流程

简介: 本文将介绍网络连接建立的过程、收发包流程,以及其中应用层、tcp层、ip层、设备层和驱动层各层发挥的作用。   应用层 对于使用socket进行网络连接的服务器端程序,我们会先调用socket函数创建一个套接字:fd = socket(AF_INET, SOCK_STREAM, 0); 以上指定了连接协议,socket调用返回一个文件句柄,与socket文件对应的inode不在磁盘上,而是存在于内存。


本文将介绍网络连接建立的过程、收发包流程,以及其中应用层、tcp层、ip层、设备层和驱动层各层发挥的作用。

 

应用层

对于使用socket进行网络连接的服务器端程序,我们会先调用socket函数创建一个套接字:

  1. fd = socket(AF_INET, SOCK_STREAM, 0);

以上指定了连接协议,socket调用返回一个文件句柄,与socket文件对应的inode不在磁盘上,而是存在于内存。

 

之后我们指定监听的端口、允许与哪些ip建立连接,并调用bind完成端口绑定:

  1. server_addr.sin_family = AF_INET;
  2. server_addr.sin_port   = htons(PORT);
  3. server_addr.sin_addr.s_addr = INADDR_ANY;
  4. bind(fd, (struct sockaddr_in *)&server_addr, sizeof(struct sockaddr_in));

端口作为进程的标识,客户端根据服务器ip和端口号就能找到相应进程。

 

接着我们调用listen函数,对端口进行监听:

  1. listen(fd, backlog);

backlog值指定了监听队列的长度,以下内核参数限制了backlog可设定的最大值:

  1. linux # sysctl -a | grep somaxconn
  2. net.core.somaxconn = 128

监听端口在listen调用后变为LISTEN状态:

  1. linux # netstat -antp | grep 9999
  2. Proto  Recv-Q Send-Q Local Address  Foreign Address  State  PID/Program name
  3. tcp         0      0  0.0.0.0:9999        0.0.0.0:* LISTEN       8709/server

相应地,客户端调用connect进行连接,tcp三次握手在connect调用返回之前完成:

img_06e58a1b2625286f62b30a478acc9c77.png

如果服务器端向客户端发送SYNACK后,客户端不返回ACK,则服务器保持半连接(SYN_RECV)状态:

  1. linux # netstat -np | grep SYN_RECV
  2. tcp      0        0     0.0.0.0:9999  127.0.0.0.1:5334   SYN_RECV  - 

若队列中的连接均处于半连接状态,服务器将不能处理正常的请求,syn泛洪攻击(syn flood)就是利用这个特点完成DoS(拒绝服务攻击)


当连接数超过队列长度backlog时,超出的连接也保持为半连接状态,直到数量达到内核参数tcp_max_syn_backlog值,超出该值的连接请求将被丢弃:

  1. linux # sysctl -a | grep tcp_max_syn
  2. net.ipv4.tcp_max_syn_backlog = 1024


accept调用用于处理新到来的连接:

  1. new_fd = accept(fd, (struct sockaddr*)&client_addr, &sin_size);

其返回一个文件描述符,后续我们可以对该文件描述符调用writeread等操作函数,原监听端口仍处于LISTEN状态:

  1. linux # netstat -antp | grep 9999
  2. tcp     0    0    0.0.0.0:9999       0.0.0.0:*      LISTEN  8709/server
  3. tcp     0    0  127.0.0.1:9999 127.0.0.1:52274 ESTABLISHED  -

以上为网络连接建立过程中,应用层所做的工作,server端完成了socket创建、端口绑定、端口监听、连接和收发包任务,而client端相对简单,只需包含连接和收发包。

 

tcp

内核代码中,tcp_sendmsgtcp发包的主入口函数,该函数中struct sk_buff结构用于描述一个数据包。

对于超过MTU(maximum transmission unit, 最大传输单元)的数据包,tcp层会对数据包进行拆分,若开启了网口的tcp segmentation offload功能,则拆分工作由网卡完成:

  1. linux # ethtool -k ether
  2. Offload parameters for eth1:
  3. rx-checksumming: on
  4. tx-checksumming: on
  5. scatter-gather: on
  6. tcp segmentation offload: on

以下内核参数是内核为tcp socket预留的用于发送数据包的缓冲区大小,单位为byte

  1. linux # sysctl -a | grep tcp_wmem
  2. net.ipv4.tcp_wmem = 4096 16384 131072

默认的用于包发送的缓冲区大小为16M

 

除了用于缓冲收发数据包,对于每个socket,内核还要分配一些数据结构用于保持连接状态,内核对tcp层可使用的内存大小进行了限制:

  1. linux # sysctl -a | grep tcp_mem
  2. net.ipv4.tcp_mem = 196608 262144 393216

以上值以页为单位,分别对应最小值、压力值和最大值,并在系统启动、tcp栈初始化时根据内存总量设定。通过proc提供的接口,我们可以查到tcp已用的内存页数:

  1. linux # cat /proc/net/sockstat
  2. sockets : used 91
  3. TCP : inuse 8 orphan 0 tw 11 alloc 13 mem 2


ip

内核代码中,ip_queue_xmit函数是ip层的主入口函数,注意ip层与tcp层操作的都是同一块内存(sk_buff结构),期间并没有发生数据包相关的内存拷贝。

ip层主要完成查找路由的任务,其根据路由表配置,决定数据包发往哪个网口,另外,该层实现netfilter的功能。

 

网络设备层

dev_queue_xmit是网络设备层的主入口函数,该层为每个网口维护一条数据包队列,由ip层下发的数据包放入对应网口的队列中。在该层中,数据包不是直接交给网卡,而是先缓冲起来,再通过软中断(NET_TX_SOFTIRQ)调用qdisc_run函数,该函数将数据包进一步交由网卡处理。我们执行ifconfig时,txqueuelen指示了网络设备层中,网口队列的长度。

 

驱动层

使用不同驱动的网卡,相应的驱动层代码就不一样,这里以e1000网卡为例。e1000_xmit_frame是该层的主入口函数,该层利用环形队列进行数据包管理,由两个指针负责维护环形队列。执行ethtool命令,我们可以查询网口驱动层环形队列长度:

  1. linux # ethtool -g eth1
  2. Ring parameters for ether
  3. Pre-set maximums:
  4. RX : 511
  5. RX Mini : 0
  6. RX Jumbo : 0
  7. TX : 511
  8. Current hardware settings:
  9. RX : 200
  10. RX Mini : 0
  11. RX Jumbo : 0
  12. TX : 511

以上RXTX分别指示收包队列与发包队列长度,单位为包个数。

 

网卡接收到数据包时将产生中断,以通知cpu数据包到来的消息,而网卡接收包又非常繁忙,如果每次收发包都向cpu发送硬中断,那cpu将忙于处理网卡中断。

相应的优化方案是NAPI(New API)模式,其关闭网卡硬中断,使网卡不发送中断,而非使cpu不接收网卡中断。在e1000驱动代码中,由e1000_clean函数实现NAPI模式。

 

不像写文件的过程,磁盘设备层完成内存数据到磁盘拷贝后,会将消息层层上报,这里的网卡驱动层发包后不会往上层发送通知消息。

 

收包过程

以上为网络发包所需经过的层次结构,以及各层的大体功能,下面我们简单看下收包过程。

 

网卡接收到数据包后,通知上层,该过程不会发生拷贝,数据包丢给ip层。

内核代码中,ip_rcvip层收包的主入口函数,该函数由软中断调用。存放数据包的sk_buff结构包含有目的地ip和端口信息,此时ip层进行检查,如果目的地ip不是本机,则将包丢弃,如果配置了netfilter,则按照配置规则对包进行转发。

 

tcp_v4_rcvtcp层收包的接收入口,其调用__inet_lookup_skb函数查到数据包需要往哪个socket传送,之后将数据包放入tcp层收包队列中,如果应用层有read之类的函数调用,队列中的包将被取出。

 

tcp层收包使用的内存同样有限制:

  1. linux # sysctl -a | grep rmem
  2. net.ipv4.tcp_rmem = 4096 16384 131072

 

目录
相关文章
|
15天前
|
Linux 开发工具 Android开发
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
ijkplayer是由Bilibili基于FFmpeg3.4研发并开源的播放器,适用于Android和iOS,支持本地视频及网络流媒体播放。本文详细介绍如何在新版Android Studio中导入并使用ijkplayer库,包括Gradle版本及配置更新、导入编译好的so文件以及添加直播链接播放代码等步骤,帮助开发者顺利进行App调试与开发。更多FFmpeg开发知识可参考《FFmpeg开发实战:从零基础到短视频上线》。
71 2
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
|
23天前
|
机器学习/深度学习 数据可视化 计算机视觉
目标检测笔记(五):详细介绍并实现可视化深度学习中每层特征层的网络训练情况
这篇文章详细介绍了如何通过可视化深度学习中每层特征层来理解网络的内部运作,并使用ResNet系列网络作为例子,展示了如何在训练过程中加入代码来绘制和保存特征图。
45 1
目标检测笔记(五):详细介绍并实现可视化深度学习中每层特征层的网络训练情况
|
23天前
|
机器学习/深度学习 编解码 算法
轻量级网络论文精度笔记(三):《Searching for MobileNetV3》
MobileNetV3是谷歌为移动设备优化的神经网络模型,通过神经架构搜索和新设计计算块提升效率和精度。它引入了h-swish激活函数和高效的分割解码器LR-ASPP,实现了移动端分类、检测和分割的最新SOTA成果。大模型在ImageNet分类上比MobileNetV2更准确,延迟降低20%;小模型准确度提升,延迟相当。
49 1
轻量级网络论文精度笔记(三):《Searching for MobileNetV3》
|
6天前
|
网络协议 安全 算法
网络空间安全之一个WH的超前沿全栈技术深入学习之路(9):WireShark 简介和抓包原理及实战过程一条龙全线分析——就怕你学成黑客啦!
实战:WireShark 抓包及快速定位数据包技巧、使用 WireShark 对常用协议抓包并分析原理 、WireShark 抓包解决服务器被黑上不了网等具体操作详解步骤;精典图示举例说明、注意点及常见报错问题所对应的解决方法IKUN和I原们你这要是学不会我直接退出江湖;好吧!!!
网络空间安全之一个WH的超前沿全栈技术深入学习之路(9):WireShark 简介和抓包原理及实战过程一条龙全线分析——就怕你学成黑客啦!
|
23天前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
40 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
23天前
|
编解码 人工智能 文件存储
轻量级网络论文精度笔记(二):《YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object ..》
YOLOv7是一种新的实时目标检测器,通过引入可训练的免费技术包和优化的网络架构,显著提高了检测精度,同时减少了参数和计算量。该研究还提出了新的模型重参数化和标签分配策略,有效提升了模型性能。实验结果显示,YOLOv7在速度和准确性上超越了其他目标检测器。
41 0
轻量级网络论文精度笔记(二):《YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object ..》
|
6天前
|
网络协议 安全 算法
网络空间安全之一个WH的超前沿全栈技术深入学习之路(9-2):WireShark 简介和抓包原理及实战过程一条龙全线分析——就怕你学成黑客啦!
实战:WireShark 抓包及快速定位数据包技巧、使用 WireShark 对常用协议抓包并分析原理 、WireShark 抓包解决服务器被黑上不了网等具体操作详解步骤;精典图示举例说明、注意点及常见报错问题所对应的解决方法IKUN和I原们你这要是学不会我直接退出江湖;好吧!!!
|
3天前
|
存储 安全 算法
网络安全与信息安全:漏洞、加密技术及安全意识的重要性
如今的网络环境中,网络安全威胁日益严峻,面对此类问题,除了提升相关硬件的安全性、树立法律法规及行业准则,增强网民的网络安全意识的重要性也逐渐凸显。本文梳理了2000年以来有关网络安全意识的研究,综述范围为中国知网中篇名为“网络安全意识”的期刊、硕博论文、会议论文、报纸。网络安全意识的内涵是在“网络安全”“网络安全风险”等相关概念的发展中逐渐明确并丰富起来的,但到目前为止并未出现清晰的概念界定。此领域内的实证研究主要针对网络安全意识现状与问题,其研究对象主要是青少年。网络安全意识教育方面,很多学者总结了国外的成熟经验,但在具体运用上仍缺乏考虑我国的实际状况。 内容目录: 1 网络安全意识的相关
|
3天前
|
SQL 安全 算法
网络安全与信息安全:漏洞、加密技术与安全意识的交织
【10月更文挑战第28天】在数字时代的浪潮中,网络安全与信息安全成为保护个人隐私和企业资产的重要盾牌。本文将深入探讨网络安全中的常见漏洞,介绍加密技术的基本概念及其在保护数据中的应用,并强调提高安全意识的重要性。通过分析具体案例和提供实用的防护措施,旨在为读者提供一个全面的网络安全知识框架,以应对日益复杂的网络威胁。
18 4
|
2天前
|
存储 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【10月更文挑战第30天】在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术以及安全意识等方面的知识,帮助读者更好地了解网络安全的重要性,提高自己的网络安全意识和技能。