Fork me on GitHub

Note for Computer Network 3

协议栈如何处理数据发送请求

副标题:阅读《网络是怎么连接的(户根勤)》读书笔记3

1

Tips:

  • IEEE802.3/802.2因长度太长、效率降低并未完全普及,更古老的以太网DIX规格仍在使用
  • TCP/IP协议以前是合为一体的,现在分开成两个
  • 像浏览器、邮件等一般的应用程序都是使用TCP收发数据的,而像 DNS 查询等收发较短的控制数据的时候则使用UDP
  • ICMP用于告知网络包传送过程中产生的错误以及各种控制消息,ARP 用于根据IP地址查询相应的以太网MAC地址
  • 套接字的实体就是通信控制信息:IP地址、端口号、通信操作的进行状态、是否收到响应、执行发送操作后经过了多长时间等

2

  • 图2.3的步骤1中,协议栈申请内存空间准备存放套接字(控制信息),刚刚创建时,数据收发操作还未开始,故写入初始状态的控制信息;之后将套接字描述符告知应用程序
  • 步骤2的连接是指双方交换控制信息,必要的信息放在了网络包的头部,另一类放在套接字内存区
    • 将浏览器查到的对方IP和端口号等告知协议栈
    • 服务器创建套接字(其实一般在服务器启动时已经创建好了),客户端将本机IP和端口号等告知服务器
    • 创建一块缓存区,用于临时存放收发的数据
    • connect详见后面段落
  • 步骤3为数据收发阶段,步骤2结束时,控制流程被交还给应用程序,应用程序调用write将数据以一大串二进制字节序列的形式交给协议栈,协议栈将数据存入发送缓存区中(不选择一次性发送是因为应用程序可能逐行或其他形式发送数据,或者积攒一定量的数据再发送以避免小包)
    • 积累多少数据才能发送,要看操作系统的种类和版本,主要看以下参数:
    • MTU参数(即一个网络包的最大长度,以太网中一般为1500字节)
    • 等待时间(避免积攒太久)
  • 步骤3补:TCP模块会设计序号ACK号,可以计算发送的某包是从第几个字节开始,长度多少了,可以用来确认遗漏情况
  • 步骤3补补:客户端在连接时需要计算出与从客户端到服务器方向通信相关的序号初始值,发送给服务器,写在SYN值中,不是从1开始,可避免网络攻击;服务器返回ACK号表示确认,并返回反方向的序号初始值,客户端接收完毕,发送ACK给服务器,服务器接收表示两个序号初始值传递完毕。注:此步操作再connect中完成
  • 步骤4,read程序接收响应,数据进入数据缓存区,在发送请求后接收响应前,read的工作会被挂起,等响应到达时再处理
  • 步骤5,调用Socket库的close程序,将TCP头部的FIN比特设为1,套接字记录断开的控制信息,同时通过IP模块向对方发送数据,对方接收到数据后,返回FIN为1和ACK的包,并更改自己的套接字为断开操作状态。此数据被协议栈调取,协议栈告知应用程序数据已经全部收到,通信结束。
  • 步骤5补,为了避免误操作,套接字会延迟删除,大约是几分钟

重要!connect过程

  1. 协议栈中的TCP 模块处创建表示连接控制信息的头部,通过 TCP 头部中的发送方和接收方端口号可以找到要连接的套接字
  2. TCP模块会将信息传递给IP模块并委托它发送
  3. 网络包由IP模块经网络发送到服务器的IP模块再传递给TCP模块
  4. 服务器的TCP模块会根据TCP头部信息找到端口号对应的套接字,服务器的套接字会改变状态为正在连接
  5. 发回响应:在TCP头部设置双方的端口号、设SYN比特(接收连接设为1,若不接受,则不设SYN,改设RST为1),设ACK比特为1(客户端向服务器发送第一个网络包时,ACK设为0,ACK比特并非前文ACK号,是一个ACK号字段的两个部分),将TCP头部传递给IP模块,委托IP模块向客户端发回响应
  6. 到达客户端的网络包通过IP模块到达TCP模块,并通过TCP头部的信息确认连接是否成功
  7. SYN为1表示连接成功,之后向套接字写入服务器的IP、端口,并将状态改为连接完毕
  8. ACK为1的响应信息已经到达客户端,相应的,客户端需要将ACK设置为1并发回服务器,告知服务器刚刚的响应包已收到,等服务器收到此包则意味着整个连接操作全部完成
  9. 此connect也有人称为’session‘,此处不作延伸

ACK号的管理

  1. 根据网络包平均往返时间调整 ACK 号等待时间,TCP采用了动态调整等待时间的方法,ACK号返回变慢,就延长ACK号等待时间
  2. 使用滑动窗口管理:在发送一个包之后,不等待 ACK 号返回,而是直接发送后续的一系列包。但是可能出现发送包的频率超过接收方处理能力的情况,严重的后果是造成缓存区溢出。避免的方法是,接收方先告诉发送方自己的承载能力,然后发送方根据这个值对数据发送操作进行控制,注:其中有个名词窗口字段,能够接收的最大数据量的大小称为窗口大小,一般与接收方的缓存区大小一致
  3. 每接收到一个包,就要向发送方传递ACK号和窗口更新这两个独立的包,会造成效率下降。解决办法:独立包发送前等待一下,凑足两个后一齐发送,可以减少包的数量

已完成全书219页

-------------The End-------------