Linux网络协议栈

2023-11-05

TCP与UDP区别

  • 区别一、是否基于连接
    TCP是面向连接的协议而UDP是无连接的协议。即TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接。
  • 区别二、可靠性 和 有序性 区别
    TCP 提供交付保证(Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输),无差错,不丢失,不重复,且按序到达,也保证了消息的有序性。该消息将以从服务器端发出的同样的顺序发送到客户端,尽管这些消息到网络的另一端时可能是无序的。TCP协议将会为你排好序。
    UDP不提供任何有序性或序列性的保证。UDP尽最大努力交付,数据包将以任何可能的顺序到达。
    TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
  • 区别三、实时性
    UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
  • 区别四、协议首部大小
    TCP首部开销20字节; UDP的首部开销小,只有8个字节 。
  • 区别五、运行速度
    TCP速度比较慢,而UDP速度比较快,因为TCP必须创建连接,以保证消息的可靠交付和有序性,毕竟TCP协议比UDP复杂。
  • 区别六、拥塞机制
    UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
  • 区别七、流模式(TCP)与数据报模式(UDP);
    TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;
    UDP是面向报文的
  • 区别八、资源占用
    TCP对系统资源要求较多,UDP对系统资源要求较少。
    TCP被认为是重量级的协议,而与之相比,UDP协议则是一个轻量级的协议。因为UDP传输的信息中不承担任何间接创造连接,保证交货或秩序的的信息。这也反映在用于承载元数据的头的大小。
  • 区别九、应用
    每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 。基于UDP不需要建立连接,所以且适合多播的环境,UDP是大量使用在游戏和娱乐场所。

TCP与UDP应用场景

TCP应用场景:
效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件远程登录

UDP应用场景:
效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)。


杂记

  1. UDP/TCP检验和是把首部和数据部分一起都校验(而IP层只检验数据报首部)
  2. UDP对应用层传下来的报文既不合并也不拆分,直接加8个字节的头部就直接转发给IP层(而TCP就不一样)
  3. MSS是TCP数据字段的报文长度:数据字段最大长度(TCP也是首部固定部分是20个字节,最长是60个字节)
  4. TCP拥塞控制过程:(通过控制发送窗口的大小)
    慢开始:每次二倍增长,直到慢开始的门限值
    拥塞避免:每次增加一个字节,直到发生超时重传
    快重传:当收到连续三个重复确认
    快恢复:窗口和门限值都变为一半,然后开始拥塞避免,重复…
  5. Linux的tcp抓包命令tcpdump
  6. IP数据报整个最大是1500个字节(IP自己的首部固定部分是20个字节,最长是60个字节)

内核常见文件

在这里插入图片描述


网络信息传输过程

在这里插入图片描述


发送端

应用层

socket

Linux系统中,socket 属于文件系统的一部分,网络通信可以被看作是对文件的读取,使得我们对网络的控制和对文件的控制一样方便。
在这里插入图片描述

UDP的socket处理过程:
在这里插入图片描述

TCP的socket处理过程:
在这里插入图片描述

应用层处理流程

  1. 网络应用调用Socket API socket (int family, int type, int protocol) 创建一个 socket,该调用最终会调用 Linux system call socket() ,并最终调用 Linux Kernel 的 sock_create() 方法
  2. 该方法返回被创建好了的那个 socket 的 file descriptor
  3. 对于每一个 userspace 网络应用创建的 socket,在内核中都有一个对应的 struct socket和 struct sock。其中,struct sock 有三个队列(queue),分别是 rx (接受), tx(发送) 和 err(错误),在 sock 结构被初始化的时候,这些缓冲队列也被初始化完成;在收据收发过程中,每个 queue 中保存要发送或者接受的每个 packet对应的 Linux 网络栈 sk_buffer 数据结构的实例 skb。(sk_buff(socket buffer)结构是linux网络代码中重要的数据结构,它管理和控制接收或发送数据包的信息。
  4. 对于 TCP socket 来说,应用调用 connect()API ,使得客户端和服务器端通过该 socket 建立一个虚拟连接。在此过程中,TCP 协议栈通过三次握手会建立 TCP 连接。默认地,该 API 会等到 TCP 握手完成连接建立后才返回。在建立连接的过程中的一个重要步骤是,确定双方使用的 Maxium Segemet Size (MSS)。
  5. 因为 UDP 是面向无连接的协议,因此它是不需要该步骤的。
  6. 应用调用 Linux Socket 的 send 或者 write API 来发出一个 message 给接收端
    sock_sendmsg 被调用,它使用 socket descriptor 获取 sock struct,创建 message header 和 socket control message
  7. _sock_sendmsg 被调用,根据 socket 的协议类型,调用相应协议的发送函数。
    对于 TCP ,调用 tcp_sendmsg() 函数。
    对于 UDP 来说userspace 应用可以调用 send()/sendto()/sendmsg() 三个 system call 中的任意一个来发送 UDP message,它们最终都会调用内核中的 udp_sendmsg() 函数

在这里插入图片描述

传输层

传输层的最终目的是向它的用户提供高效的、可靠的和成本有效的数据传输服务,主要功能包括 :
(1)构造 TCP segment
(2)计算 checksum
(3)发送回复(ACK)包
(4)滑动窗口(sliding windown)等保证可靠性的操作。
TCP 协议栈的大致处理过程如下图所示:
在这里插入图片描述

TCP 栈简要过程:

  1. tcp_sendmsg 函数会首先检查已经建立的 TCP connection 的状态,然后获取该连接的 MSS,开始 segement 发送流程。
  2. 构造 TCP 段的 playload:它在内核空间中创建该 packet 的 sk_buffer 数据结构的实例 skb,从 userspace buffer 中拷贝 packet 的数据到 skb 的 buffer。
  3. 构造 TCP header。
  4. 计算 TCP 校验和(checksum)和 顺序号 (sequence number)。
  5. TCP 校验和是一个端到端的校验和,由发送端计算,然后由接收端验证。其目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。如果接收方检测到校验和有差错,则TCP段会被直接丢弃。TCP校验和覆盖 TCP 首部和 TCP 数据
  6. 发到 IP 层处理:调用 IP handler 句柄 ip_queue_xmit,将 skb 传入 IP 处理流程。

UDP 栈简要过程:

  1. UDP 将 message 封装成 UDP 数据报
  2. 调用 ip_append_data() 方法将 packet 送到 IP 层进行处理。

IP 网络层 - 添加header 和 checksum,路由处理,IP fragmentation

网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。网络层将数据链路层提供的帧组成数据包,包中封装有网络层包头,其中含有逻辑地址信息- -源站点和目的站点地址的网络地址。
其主要任务包括
(1)路由处理,即选择下一跳
(2)添加 IP header
(3)计算 IP header checksum,用于检测 IP 报文头部在传播过程中是否出错
(4)可能的话,进行 IP 分片
(5)处理完毕,获取下一跳的 MAC 地址,设置链路层报文头,然后转入链路层处理。


接收端

传输层 (TCP/UDP)

  1. 传输层 TCP 处理入口在 tcp_v4_rcv 函数(位于 linux/net/ipv4/tcp ipv4.c 文件中),它会做 TCP header 检查等处理。
  2. 调用 _tcp_v4_lookup,查找该 package 的 open socket。如果找不到,该 package 会被丢弃。
  3. 接下来检查 socket 和 connection 的状态。
  4. 如果socket 和 connection 一切正常,调用 tcp_prequeue 使 package 从内核进入 user space放进 socket 的 receive queue。然后 socket 会被唤醒,调用 system call,并最终调用 tcp_recvmsg 函数去从 socket recieve queue 中获取 segment。

接收端 - 应用层

  1. 每当用户应用调用 read 或者 recvfrom 时,该调用会被映射为/net/socket.c 中的 sys_recv 系统调用,并被转化为 sys_recvfrom 调用,然后调用 sock_recgmsg 函数。
  2. 对于 INET 类型的 socket,/net/ipv4/af inet.c 中的 inet_recvmsg 方法会被调用,它会调用相关协议的数据接收方法。
  3. 对 TCP 来说,调用 tcp_recvmsg。该函数从 socket buffer 中拷贝数据到 user buffer。
  4. 对 UDP 来说,从 user space 中可以调用三个 system call recv()/recvfrom()/recvmsg() 中的任意一个来接收 UDP package,这些系统调用最终都会调用内核中的 udp_recvmsg 方法。

sk_buff 是什么

当网络包被内核处理时,底层协议的数据被传送更高层,当数据传送时过程反过来。由不同协议产生的数据(包括头和负载)不断往下层传递直到它们最终被发送。因为这些操作的速度对于网络层的表现至关重要,内核使用一个特定的结构叫 sk_buff, 其定义文件在 skbuffer.h。Socket buffer被用来在网络实现层交换数据而不用拷贝来获取数据包 –这显著获得速度收益。

sk_buff 是 Linux 网络的一个核心数据结构,其定义文件在 skbuffer.h。
socket kernel buffer (skb) 是 Linux 内核网络栈(L2 到 L4)处理网络包(packets)所使用的 buffer,它的类型是 sk_buffer。简单来说,一个 skb 表示 Linux 网络栈中的一个 packet;TCP 分段和 IP 分组生产的多个 skb 被一个 skb list 形式来保存。
struct sock 有三个 skb 队列(sk_buffer queue),分别是 rx , tx 和 err。
在这里插入图片描述

struct sk_buff {
    /* These two members must be first. */ # packet 可以存在于 list 或者 queue 中,这两个成员用于链表处理
    struct sk_buff        *next;
    struct sk_buff        *prev;
    struct sk_buff_head    *list; #该 packet 所在的 list
 ...
    struct sock        *sk;      #跟该 skb 相关联的 socket
    struct timeval        stamp; # packet 发送或者接收的时间,主要用于 packet sniffers
    struct net_device    *dev;  #这三个成员跟踪该 packet 相关的 devices,比如接收它的设备等
    struct net_device    *input_dev;
    struct net_device    *real_dev;

    union {                  #指向各协议层 header 结构
        struct tcphdr    *th;
        struct udphdr    *uh;
        struct icmphdr    *icmph;
        struct igmphdr    *igmph;
        struct iphdr    *ipiph;
        struct ipv6hdr    *ipv6h;
        unsigned char    *raw;
    } h;

    union {
        struct iphdr    *iph;
        struct ipv6hdr    *ipv6h;
        struct arphdr    *arph;
        unsigned char    *raw;
    } nh;

    union {
        unsigned char    *raw;
    } mac;

    struct  dst_entry    *dst; #指向该 packet 的路由目的结构,告诉我们它会被如何路由到目的地
    char            cb[40];    # SKB control block,用于各协议层保存私有信息,比如 TCP 的顺序号和帧的重发状态
    unsigned int        len, #packet 的长度
                data_len,
                mac_len,       # MAC header 长度
                csum;          # packet 的 checksum,用于计算保存在 protocol header 中的校验和。发送时,当 checksum offloading 时,不设置;接收时,可以由device计算

    unsigned char        local_df, #用于 IPV4 在已经做了分片的情况下的再分片,比如 IPSEC 情况下。
                cloned:1, #在 skb 被 cloned 时设置,此时,skb 各成员是自己的,但是数据是shared的
                nohdr:1,  #用于支持 TSO
                pkt_type, #packet 类型
                ip_summed; # 网卡能支持的校验和计算的类型,NONE 表示不支持,HW 表示支持,

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

Linux网络协议栈 的相关文章

随机推荐

  • case when then else end语句的用法

    case具有两种格式 简单case函数和case搜索函数 简单case函数 case sex when 1 then 男 when 2 then 女 else 其他 end case搜索函数 经常用的是这个 case when sex 1
  • Java中字符编码问题和中文占几个字节的问题(ASCII Unicode UTF-8 )

    ASCII码 在计算机内部 所有的信息最终都表示为一个二进制的字符串 每一个二进制位 bit 有0和1两种状态 因此八个二进制位就可以组合出256种状态 这被称为一个字节 byte 也就是说 一个字节一共可以用来表示256种不同的状态 每一
  • layuiAdmin 框架单页面文档

    快速入门 部署 解压文件后 将 layuiAdmin 完整放置在任意目录 通过本地 web 服务器去访问 start index html 即可运行 Demo 由于 layuiAdmin 可采用前后端分离开发模式 因此你无需将其放置在你的服
  • STM32编译报错 Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f10x_hd.o).——解决办法

    入门STM32写第一个程序时 引入启动文件startup stm32f10x hd s后编译报错 注 启动文件自行下载后加入工程中 一 原因 引入的启动文件startup stm32f10x hd s中 外部引用的SystemInit函数是
  • Spring Cloud Stream Binder 实现

    Spring Cloud Stream Binder 实现 JMS 实现 ActiveMQ 1 增加Maven依赖
  • unity4升级unity5动画文件不能正常播放解决方法

    using UnityEngine using System Collections using UnityEditor public class ZYResetTheAnimator MonoBehaviour MenuItem ZY R
  • 【python基础】爬虫练习

    不知道大家有没有通过豆瓣网寻找一些排名较高的电影 反正小编基本上是顺着排名一点点找电影看 本文将详细介绍如何使用Python爬虫抓取豆瓣网电影评论用户的观影习惯数据 并进行简单的数据处理和分析 目录 一 配置环境 1 1 安装Python
  • html2Canvas + jsPDF vue生成pdf(A4纵向或A3横向)

    1 第一个 将页面html转换成图片 npm install save html2canvas 第二个 将图片生成pdf npm install jspdf save 2 创建名称 htmlToPdf js 页面导出为pdf格式 impor
  • SpringBoot使用Swagger配置API接口文档

    概述 Swagger是一个用于设计 构建和文档化 RESTful API 的开源框架 它提供了一组工具 使得开发人员能够更轻松地定义 描述和测试API接口 具体来说 Swagger包含以下几个核心组件 Swagger规范 Swagger S
  • LaTeX Error: Unicode character解决方法

    由tex编译到pdf时报错信息如下 解决办法如下 第一步 在引用包的位置中添加 usepackage CJKutf8 并且在 begin document 下方添加 begin CJK UTF8 gbsn 第二步 在 end documen
  • torch将多个tensor张量合并为一个张量,只提高迷你批次的纬度

    在自己写pytorch的数据集加载函数时 会遇到一个问题 如何将多张图片张量合并到一起 提升迷你批次batch的纬度 但是不影响图片的大小和RGB通道数 解决方法 函数torch cat inputs dim 这里的inputs是你要合并的
  • 华为OD题目: 核酸检测人员安排

    核酸检测人员安排 参考 https blog csdn net qq 34465338 article details 128648074 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 在系统 网络均正常的情况下组织核酸
  • idea 使用 git 回退到某个历史版本

    idea 使用 git 回退到某个历史版本 有时我们提交git错了 想回滚 怎么办 一 用idea工具 1 idea中打开Terminal 输入 git log 显示历史提交记录 或者 右击项目 gt Git gt Show History
  • MongoDB $unwind保留空数组

    MongoDB的aggregate的pipeline中 有 unwind操作符 该操作符用于延展某一个数组类型的元素 作用与Python中的flatten 拍平 类似 但是在实际使用中 unwind 有一个非常明显的问题 就是如果要unwi
  • H.264码流分析仪

    目录 一 实验内容 二 实验结果 1 SPS profile idc level idc eq parameter set id log2 max frame num minus4 pic order cnt type log2 max p
  • @ApiModelProperty注解

    ApiModelProperty 用于方法 字段 表示对model属性的说明或者数据操作更改 value 字段说明 name 重写属性名字 dataType 重写属性类型 required 是否必填 example 举例说明 hidden
  • 电脑视频显示服务器运行失败,抖音直播伴侣提示:服务器终点无法运行操作或者创建视频源失败请重试解决方法视频教程...

    1 抖音直播伴侣多开 如果提示 服务器终点无法运行操作 或者创建视频源失败 请重试 多开插件一般是操作系统不兼容 要换操作系统 或者安装虚拟机 我推荐的操作系统是WIN10 64位 我拿了100多个操作系统测试 最终这个版本的稳定 可用 大
  • 图像分割套件PaddleSeg全面解析(四)数据预处理

    本部分主要介绍一下数据增强部分 PaddleSeg套件里把数据增强部分都定义在transforms里面 与Pytorch比较类似 这样就把一些基本的图像处理方法 缩放 归一化等 和数据增强 随机裁剪 翻转 颜色抖动 统一了 自己新增的数据增
  • 编程15年40岁程序员的我终于在压力下被迫转行了

    本人今年40岁多了 中山大学计算机小硕 已经从事it工作15年多 最后一次工作是2017年 创业 互联网教育方向 2020年失败关闭公司 创业失败后 在家沉淀了几个月 然后决定再次找工作 前几年频繁接到猎头电话的我 海投了不少公司 结果都渺
  • Linux网络协议栈

    TCP与UDP区别 区别一 是否基于连接 TCP是面向连接的协议 而UDP是无连接的协议 即TCP面向连接 UDP是无连接的 即发送数据之前不需要建立连接 区别二 可靠性 和 有序性 区别 TCP 提供交付保证 Tcp通过校验和 重传控制