加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

TCP/IP协议栈之数据包如何穿越各层协议

发布时间:2019-08-25 00:22:50 所属栏目:教程 来源:架构师之路
导读:所有互联网服务,均依赖于TCP/IP协议栈。懂得数据是如何在协议栈传输的,将会帮助你提升互联网程序的性能和解决TCP相关问题的能力。 我们讲述在Linux场景下数据包是如何在协议层传输的。 1. 发送数据 应用层发送数据的过程大致如下: 我们把上述处理过程的
副标题[/!--empirenews.page--]

所有互联网服务,均依赖于TCP/IP协议栈。懂得数据是如何在协议栈传输的,将会帮助你提升互联网程序的性能和解决TCP相关问题的能力。

我们讲述在Linux场景下数据包是如何在协议层传输的。

1. 发送数据

应用层发送数据的过程大致如下:

TCP/IP协议栈之数据包如何穿越各层协议(绝对干货)

我们把上述处理过程的区域大致分为:

  • User区域
  • Kernel 区域
  • Device区域

在user和kernel区域的任务都是由本机cpu执行,这两个区域合并称为host区域,以区分device区域(网络接口卡上有单独的cpu)。device是接收和发送数据包的网络接口卡(Network Interface Card),一般也称为LAN card。

当应用程序调用write(fd, buf, len)来发送数据时,用户态区域会进入内核态区域,建立这个关系的纽带是socket fd和系统调用write。

在内核态的socket有两个buffer:

  • send socket buffer,用于发送数据
  • receive socket buffer,用于接收数据

当write系统调用被执行,用户态的数据(buf,长度)会被拷贝到内核区域的内存,并被放入到send socket buffer的末尾(见下图,发送是按照顺序发送的),然后TCP就会被调用。

TCP/IP协议栈之数据包如何穿越各层协议

TCP中的数据结构是TCB(TCP Control Block)。TCB包含了执行TCP会话所需要的信息,包括TCP连接状态,接收窗口,拥塞窗口,序号,重传timer 等。

TCP会创建TCP数据分段,而TCP数据分段包括TCP header和payload,如下图:

TCP/IP协议栈之数据包如何穿越各层协议(绝对干货)

Payload是待发送的socket buffer中的数据,而TCP header是为了TCP可靠发送数据而加的辅助信息。

这些数据分段会进入到IP层,IP层会加上IP头部信息到数据分段,如下图:

TCP/IP协议栈之数据包如何穿越各层协议(绝对干货)

IP在执行路由之前会去检查Netfilter LOCAL_OUT钩子,看是否需要执行iptables相关配置。之后执行IP路由。IP路由主要功能是寻找下一跳(例如网关或路由器)的IP地址,而路由的目的是到达目的地IP地址所在的机器。

IP执行路由之后,检查Netfilter POST_ROUTING钩子,如果有iptables在这方面的配置,就会去执行相关操作。委托给数据链路层之前,IP层还会执行ARP(网络地址转换),通过下一跳IP地址来查找目的MAC地址,并把Ethernet头部添加到IP数据包,如下图。

TCP/IP协议栈之数据包如何穿越各层协议(绝对干货)

IP层同时还给用户提供了raw socket接口,即发送数据包的接口。raw socket发送的数据包与正常流程的数据包不一样,在执行Netfilter的时候,会跳过这些钩子。

IP层做完工作以后,会把数据包(上图中的数据包,一般称frame)委托给数据链路层。

由于ARP已经把目的MAC地址写入到数据包头部,这样就减轻了驱动driver的工作。进入数据链路层后,内核会去检测是否有抓包工具在监听抓包(例如tcpdump),如果有,内核会拷贝数据包信息到抓包工具的内存地址空间。

之后,根据一定的协议规则,驱动driver会要求NIC传递这个数据包。当NIC收到这个请求后,NIC复制数据包到自己的内存里,并且发送给网络。当NIC发送完一个数据包,会产生一个中断, 主机 cpu去执行中断处理程序,完成后续工作。

2. 接收数据

应用程序接收数据的过程大致如下:

TCP/IP协议栈之数据包如何穿越各层协议(绝对干货)

首先NIC把数据包写入自己的内存,并校验数据包是不是有效的,如果是有效的,把数据包写入主机的内存空间,然后NIC给主机操作系统发送一个中断信号,这时就进入到kernel区域。

在数据链路层,内核首先会做数据包检测,然后Driver驱动把数据包进行改装,以便后续TCP/IP能够理解这个数据包。改装完以后,根据Ethernet头部信息中的Ethertype分发给上层,假设为IPv4,去除Ethernet头部,并发送给IP层。值得注意的是,委托给IP层之前,如果有抓包工具在监听抓包,那么内核就会拷贝数据包信息到抓包工具的内存地址空间。

IP层通过计算checksum来校验IP头部的checksum是否有效,如果有效,接着检查PRE_ROUTING钩子(比如查看是否有iptables的相应配置需要执行),然后执行IP路由,IP路由会判断这个数据包是本地处理还是转发当前数据包到其它主机。如果是转发数据包,执行FORWARD和POST_ROUTING钩子,并转发给数据链路层;如果是本地处理,IP还会检查LOCAL_IN钩子,执行完以后,根据IP头部信息的proto值,假设为TCP,去除IP头部,并把数据包传递给上层TCP。值得注意的是,委托给TCP层之前,如果有raw socket在监听抓包,那么内核会拷贝数据包信息到raw socket的内存地址空间(默认tcpcopy利用raw socket来监听IP层的数据包)。

TCP层会根据TCP checksum来检测数据包是否有效(如果采用了checksum offload,NIC会去做相关计算),然后就给这个数据包查找相应的TCB(TCP control block),查找的方法是通过如下组合信息来查找:

  1. <source IP, source port, target IP, target port> 

如果没有查到,一般会发送reset数据包;如果查到了,进入TCP数据包处理环节。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读