note-网络是怎样连接的2 协议栈和网卡

助记提要
  1. 协议栈的结构
  2. 协议栈创建连接的实际过程
  3. 协议栈发送数据包的2个判断依据
  4. TCP确认数据收到的原理
  5. 断开连接的过程
  6. 路由表和ARP
  7. MAC地址的分配
  8. MAC模块的工作
  9. 通过电信号读取数据的原理
  10. 网卡和协议栈接收包的过程
  11. ICMP
  12. UDP协议的适用场景

2章 用电信号传输TCP/IP数据 探索协议栈和网卡

1. TCP部分

1.1 协议栈

底层实际负责收发消息的是协议栈、网卡驱动和网卡。协议栈是操作系统中的网络控制软件,

操作系统的协议栈分为上下两部分。上部分为两块,分别是用TCP协议收发数据的部分和用UDP协议收发数据的部分。一般应用程序都使用TCP收发数据,像DNS查询等收发较短的控制数据时用UDP。
下部分是IP协议部分,负责将切分的网络包发送给通信对象。这一层还有ICMP和ARP协议。ICMP用于报告网络包传输过程中的错误和控制信息,ARP用于根据IP地址查询MAC地址。
协议栈下面是网卡驱动程序,负责控制网卡硬件。再下是网卡,负责实际的收发操作。

协议栈内有一块用于存放控制信息的内存空间,记录了通信对象的IP地址、端口号、通信状态等信息。这些控制信息就是套接字的实体。
创建套接字时,先分配一个内存空间,然后在其中写入初始状态。

1.2 TCP头部格式
字段长度(位)含义
发送方端口号16发送网络包的程序的端口号
接收方端口号16接收方程序的端口号
序号32发送方告诉接收方,当前网络包是所有发送数据的第几个字节
ACK号32接收方告诉发送方已收到了所有数据的第几个字节
数据偏移量4数据部分的起始位置,相当于头部的长度
保留6保留字段,未使用
控制位66个比特位表示不同的通信控制含义:
URG:表示紧急指针字段有效;
ACK:表示接收数据序号字段有效,数据已被接收到;
PSH:表示通过flush操作发送的数据;
RST:强制断开连接,用于异常中断情况;
SYN:发送方和接收方相互确认序号,表示连接操作;
FIN:表示断开连接
窗口16接收方告知发送方窗口大小。即无需等待确认可一起发送的数据量
校验和16用于检验是否出现错误
紧急指针16表示需要紧急处理的数据位置
可选字段可变额外添加的可选字段

通信操作使用的控制信息,一是数据包头部记录的信息,二是套接字中记录的信息。

1.3 连接操作实际过程

连接操作表示通信双方交换控制信息,在套接字中记录这些必要信息并准备数据收发的一系列操作。(三次握手)

1-1 应用程序调用socket库的connect组件,服务器的IP和端口号被传递给协议栈的TCP模块;
1-2 TCP模块创建包含控制信息的头部。其中SYN位设为1,表示连接;
1-3 TCP模块把信息交给IP模块,IP模块进行网络包发送;
1-4 服务器的IP模块收到的数据传递给TCP模块;
1-5 服务器的TCP模块根据头部的端口号找到对应的套接字,在这个套接字写入相应信息,将状态改为正在连接;
2-1 服务器的TCP模块创建响应,响应的TCP头部的ACK控制位为1,表示成功接收到客户端发来的网络包。
2-2 服务器TCP模块把TCP头部交给IP模块,由IP模块向客户端返回响应;
2-3 客户端收到后,TCP模块通过头部信息确认连接操作是否成功。SYN为1表示连接成功,就向套接字写入服务器的IP地址、端口号等信息,同时连接状态改为连接完毕。
3 客户端将ACK位设为1后,发回服务器,告诉服务器刚才的响应已收到。

1.4 协议栈发送数据的两种依据

协议栈收到数据后不是马上发送出去,而是先将数据存在发送缓冲区中。

应用程序交给协议栈发送的数据的长度是应用程序决定的,有的应用程序会一次性传递所有数据,有的会逐字节或逐行传递数据。如果一收到数据就马上发送,就可能会发送大量小包,导致网络效率下降,因此需要积累到一定量再发送。

MTU,表示网络包的最大长度,以太网中一般为1500字节。
MSS,表示除去头部后,网络包能容纳的TCP数据的最大长度。

  1. 协议栈会在从应用程序收到的数据长度超过或接近MSS时再发送出去,避免发送太多小包;
  2. 协议栈内部有计时器,当应用程序发送频率低时,为避免等待过长时间造成延迟,经过一定时间后就会把网络包发送出去。

长度和时间这两个判断依据是相互冲突的。协议栈会由于操作系统差异有不同的表现。应用程序可以在发送数据时指定选项,控制协议栈的发送操作。

应用层的大数据包到达发送缓冲区后,会被以MSS长度为单位进行拆分,拆分的每块数据会被放入单独的网络包中。发送时,在每一块数据前面加上TCP头部,然后交给IP模块执行发送操作。

1.5 TCP确认网络包收到的原理
  1. TCP模块拆分数据时,会计算出每一块数据相当于从头开始的第几个字节,这个字节数会写在TCP头部的序号字段。
  2. 接收方收到网络包时,通过序号知道这次的数据是从第几个字节开始的。并使用网络包的长度减去头部长度算出数据长度。
  3. 接收方根据序号和数据长度判断有无遗漏。
  4. 如果没有遗漏,就把目前收到的数据长度写到ACK号中返回给发送方。
  5. 发送方通过ACK号得知对方收到了多少数据。

为了避免发送过程被攻击者预测到,实际发送时的序号初始值是随机的。建立连接时,将SYN置为1的同时,也会将序号改为初始的随机值,用来告知服务器。
TCP在得到对方确认收到数据的消息前,发送过的数据都会保存在发送缓冲区中。如果对方没有返回某些包对应的ACK号,就重新发送这些包。
TCP的确认机制很强大,因此应用程序、网卡、集线器、路由器等都没有错误补偿机制,检测到错误就直接丢弃。

1.6 ACK号
  • ACK号的等待时间
    ACK号的返回快慢受很多因素影响,如网络距离的远近、网络的拥塞程度等。
    因此ACK号的等待时间不能设为固定的值。
    TCP会在发送数据的过程中持续监测ACK号的返回时间,如果返回变慢,就延长等待时间,如果ACK号马上返回,就缩短等待时间。

  • 使用窗口管理ACK号
    发送数据包后,等待ACK号的时间如果什么也不做,会很浪费。因此在等待ACK号的期间继续发送后续的包,这样的方式叫滑动窗口。这种方式减少了等待ACK号的时间浪费。

    接收方的TCP收到包后,会把数据存到接收缓冲区,然后组装数据、计算ACK号、传递给应用程序。在操作期间,下一个包到了,会被暂存到接收缓冲区。如果数据到达的速率超过处理速率,缓冲区的数据会越来越多直到溢出。缓冲区溢出后就收不到后续的包了。
    为了避免这种情况,接收方需要通过窗口字段告诉发送方自己能接收多少数据量,发送方按照这个值控制发送操作。
    接收方能接收的最大数据量称为窗口大小,经常用于TCP调优。

    接收方接收完数据后就需要返回ACK号,在数据传递给应用程序后就需要更新窗口大小。如果每收到一个包就向发送方分别发送ACK号和窗口更新,会使网络效率下降。
    因此接收方在发送ACK号和窗口更新时,不会马上把包发送出去,而是等待一段时间,将两种通知合并在一个包里发送。连续的ACK号和连续的窗口更新也能进行合并。

  • 接收HTTP响应消息
    请求消息发送完后,应用程序会调用read程序获取响应消息。协议栈会取出暂存到接收缓冲区的数据传递给应用程序。如果这时请求刚发出去,接收缓冲区没有数据,协议栈会将应用程序的委托挂起,等待响应消息到达后再继续操作。

1.7 断开连接过程

数据发送完毕后,断开连接的过程(四次挥手):

  1. 服务器端的应用程序调用socket库的close程序;
  2. 服务器的协议栈生成包含断开信息的TCP头部,其中的FIN位设为1;
  3. 协议栈委托IP模块把数据发送个客户端;
  4. 客户端收到服务器发来的FIN为1的TCP头部后,把自身的套接字标记为断开操作状态;
  5. 客户端协议栈向服务器返回一个ACK号,告知服务器已收到断开信息;
  6. 客户端应用程序得知服务器的数据已经全部收完后,调用close程序结束数据收发操作;
  7. 之后,客户端的协议栈生成一个FIN为1的TCP包发给服务器;
  8. 服务器收到后返回ACK信号,结束通信。
  9. 客户端等待一段时间后,删除套接字。等待是为了避免误操作。

HTTP1.0中服务器发送完响应后就发起断开过程;HTTP1.1后服务器不主动断开,而是客户端在没有新请求时发起断开。

2. IP部分

2.1 IP头部

IP模块的工作就是在包前面加上IP头和MAC头。IP头包含IP协议规定的、根据IP地址将包发往目的地需要的控制信息。MAC头部包含通过以太网的局域网把包传输到最近的路由器的控制信息。

字段长度含义
版本号4IP协议的版本号
头部长度4IP头部的长度。会因可选字段而变化
服务类型8表示包传输的优先级
总长度16IP消息的总长度
ID号16用于识别包的编号,一般为包的序列号。如果包被IP分片,则所有分片有相同的ID
标志3仅两位有效,一位表示是否允许分片,另一位表示是否为分片包
分片偏移量13当前包的内容为整个IP消息的第几个字节开始的内容
生存时间8包的生存时间。为了避免网络出现会环,导致一个包永远在网络中转发。没经过一个路由器,这个值会减1,减到0时这个包会被丢弃
协议号8表示协议的类型。十六进制表示:TCP为06,UDP为17,ICMP位01
头部校验和16用于检查错误。现已不再使用
发送方IP地址32发送方的IP地址
接收方IP地址32接收方的IP地址
可选字段可变长度可选的其他控制信息。一般很少用到
  • IP模块如何使用路由表
    路由表的每行包括目标子网地址(Network Destination)、转发路由器的IP地址(Gateway)、发送包的网络接口(Interface)、使用该行路由的传输成本(Metric)。
    TCP模块告知目标IP地址后,IP模块在路由表中找这个地址所在的网络,找到后把包由Interface记录的网卡发送给Gateway记录的路由器。路由表第一行是默认网关,无法匹配时会使用这一行。

发送方的计算机上可能会有多块网卡,因此IP地址填写的是发送使用的网卡的IP地址。

2.2 MAC头部

以太网判断网络包目的地的方式和TCP/IP不同,因此需要采用相匹配的方式才能在以太网将包发到目的地。

字段长度含义
接收方MAC地址48网络包接收方的MAC地址
发送方MAC地址48网络包发送方的MAC地址
以太类型16使用的协议类型。0800:,IP协议;0806,ARP协议;86DD,IPv6协议;0000-05DC,IEEE 8-2.3。TCP/IP中只用到0800和0806两种
2.3 接收方MAC地址的获取

路由表中能找到把网络包发给谁(Gateway),但是只知道对方的IP地址,不知道MAC地址。

  • ARP(Address Resolution Protocol)
    地址解析协议。ARP会对同一子网中的所有设备广播,询问某个IP地址和哪个MAC地址对应。
    内存中有一块ARP缓存,其中保存了之前的查询结果。在发送ARP包前先查询缓存,避免网络中增加过多的ARP包。ARP缓存有效期一般为几分钟。

MAC头部是以太网需要的信息,却由IP模块装配。这样网卡只做单纯的发送和接收,一块网卡也能支持各种类型的包。

3. 网卡部分

3.1 以太网模型的发展
  • 初始原型
    通过收发器把不同网线的信号连接起来。一台计算机发信号时,信号会流过整个网络,到达所有设备。和MAC头部的接收者地址匹配的设备接收信号包,其他设备丢弃这些包。
  • 使用中继式集线器
    主干网线替换为了中继式集线器,收发器网线替换为双绞线。信号仍然会到达所有设备。
  • 使用交换式集线器
    信号只会到达MAC地址指定的设备。

以太网的三个性质:将包发送到MAC头部接收方MAC地址表示的目的地,用发送方MAC地址识别发送方,用以太类型识别包的内容。

3.2 MAC模块的MAC地址

启动操作系统时,网卡驱动会对硬件进行初始化操作,包括硬件错误检查、初始设置等。
初始化时,有一项是为MAC模块设置MAC地址。网卡的ROM中保存着全世界唯一的MAC地址,是在生产网卡时写入的,读出后就能对MAC模块进行设置。也能通过命令行或配置文件读取MAC地址并分配给MAC模块,这时会忽略ROM中的MAC地址。

3.3 MAC模块的工作

收到IP模块的包后,MAC模块会把包从缓冲区取出,并在开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列FCS。

  • 报头用来测量时钟信号,长度56比特。
  • 起始帧分界符用于标记包的起始位置,长度8比特。
  • 末尾的帧校验序列用于检测传输过程中因噪声导致的波形紊乱、数据错误,长度32比特。数据发生变化时,接收方计算出的FCS和发送方的就会不一致。
3.4 如何使用电信号读取数据

0和1两种比特可以使用特定的电压和电流表示,但是当信号为连续的1或0时,比特之间的界限会消失,读取时无法判断。
解决这个问题的方式是加一组用于区分比特间隔的时钟信号。两组信号需要叠加在一起发送(避免传输太远导致偏移)。
时钟信号一般是固定的频率变化的,只要对信号观察一段时间,就能知道变化的周期。

3.5 半双工模式的问题

发送信号的操作一种是集线器的半双工模式,另一种是交换机的全双工模式。
MAC模块会把处理完的网络包转换为通用的电信号交给网卡的PHY(MAU)模块,PHY把信号转换为可在网线中传输的格式,然后通过网线发出去。

信号碰撞,在使用集线器的半双工模式中,发送信号的过程中,接受线路也有信号进来时,两组信号就会发生叠加,无法彼此区分。
此时会终止发送操作,并发送一段时间的阻塞信号让其他设备也停止发送。等待一段时间后重试发送。等待时间是按照MAC地址生成一个随机数计算出来的,重试时又发生碰撞会将等待时间延长一倍。重试10次后不行就报错。

3.6 接收返回包的过程
3.6.1 网卡接受包的过程

PHY(MAU)把收到的信号转为通用格式发给MAC模块,MAC模块把信号转为数字信息,放到缓冲区中。
在到达FCS时,会把报头到结尾的比特套用公式计算出FCS和包尾的FCS作比较,错误包会被丢弃。FCS校验正确后,如果MAC头部中接收方的MAC地址和网卡初始化时分配的MAC地址一致,MAC模块就把包放到缓冲区中。

网卡通过中断机制通知计算机收到一个包。
网卡先向扩展总线中的中断信号线发送信号,该信号线通过计算机的中断控制器连接到CPU。CPU收到中断信号时,会挂起当前任务,转到中断处理程序。中断处理程序调用网卡驱动。网卡驱动从缓冲区中取出收到的包,通过MAC头部的以太类型判断协议类型,然后将数据交给对应的协议栈。

中断是有编号的。网卡安装时在硬件中设置中断号,中断处理程序会把中断号和相应的驱动绑定。

3.6.2 协议栈接收数据

TCP/IP协议栈收到网卡发来的数据,IP模块会检查IP头的格式,确定接收方的IP地址与网卡的地址一致。
如果接收到的包是经过分片的,IP模块会先暂存在内存中,等全部的相同ID的包到达后还原为原始的包。

之后数据包交给TCP模块。TCP模块根据IP头部的接收方和发送方IP地址,以及TCP头部的接收方和发送方端口号找到对应的套接字,执行后续的操作。

查找套接字同时需要接收方和发送方的IP地址和端口号,所以TCP模块需要查询IP头部的信息。TCP和IP模块被看成一个整体,没有严格划分。

3.6.3 ICMP

ICMP协议用于传输出错时报告错误信息。属于网络层协议,主要在主机和路由器之间传递控制信息。IP数据无法访问目标、IP路由器无法按当前速率转发数据包时会自动发ICMP消息。

  • ICMP规定的各种消息类型
    | 消息 | 类型 | 含义 |
    | — | — | — |
    | Echo reply | 0 | 响应Echo消息 |
    | Destination unreachable | 3 | 出于某些原因包没有到达目的地而是被抛弃,通过此消息通知发送方。可能原因包括IP地址在路由表中不存在;目标端口不存在对应套接字;需要分片,但分片被禁用 |
    | Source quench | 4 | 发送的包数超过路由器的转发能力时,超过的包会被丢弃,这时会通知发送方。路由器的性能不够时,可能不会发送该消息,而是直接丢弃多余的包。 |
    | Redirect | 5 | 查路由表发现包的入口和出口为同一个网络接口时,表示该包不需要这个路由器转发,发送方可以直接发给下一个路由器。此时路由器会发送这条消息,告知发送方下一个路由器的地址。 |
    | Echo | 8 | ping命令发送的消息,收到这条消息的设备需要返回Echo reply消息,以确认通信对象是否存在。 |
    | Time exceeded | 11 | 超过了IP头部中的TTL字段表示的存活时间,被路由器抛弃。 |
    | Parameter problem | 12 | 由于IP头部字段存在错误而被丢弃。 |

4 UDP协议

4.1 UDP头部
名称长度含义
发送方端口号16发送方的端口号
接收方端口号16接收方的端口号
数据长度16UDP头部后面数据的长度
校验和16用于校验错误
4.2 UDP适用场景
  1. 不需要重发的数据
    在数据长,分包多的情况下,发生漏包时,为了高效传输,TCP只重发出错或者未送达的包。

  2. 控制用的短数据
    控制数据一般很短,一个包的大小就能容纳。
    这时使用UDP,不需要建立和断开连接的开销。出错时,协议栈也不会知道。应用程序在没有收到对方的回复时会选择重发数据。

  3. 音频和视频数据
    音频和视频数据有规定的送达时间,送晚了就会错过播放时机。
    重发需要消耗时间,也很可能错过播放时机。
    某些包缺少了只会产生一些失真和卡顿,是可接受的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值