计算机技术学习札记

计算机网络 4:传输层

本层……

  • 提供逻辑上「端到端」的连接,中间路径不管。

  • 采用「端口」进行多路复用,不同进程(服务)工作在不同的端口上。

  • 二元组 {目的 IP,目的端口号}(UDP)或四元组 {源 IP,源端口号,目的 IP,目的端口号}(TCP)确定一个连接。

UDP

一种无连接、尽力而为的传输层协议。UDP 头部如下:

字节2222
结构源端口号目的端口号包含头部的长度校验和数据

其中校验和计算时,还需要在 UDP 段前方加上「伪头部」:

字节44112
结构源 IP 地址目的 IP 地址全零协议号(从 IP 头部取出)UDP 包含头部的长度

TCP

一种可靠的、点对点的、全双工的、面向连接的传输层协议。TCP 头部如下:

(Wikipedia,本站没有实现复杂表格排版所以画不出来这种表格)

TCP 使用滑动窗口的确认机制实现可靠传输。

  • 序列号(SEQ):指 TCP 段中第一个字节的编号(不是第几个段)。

  • 确认号(ACK):指希望接收到的下一个段,第一个字节的编号——减 1 即本机已经收到的字节编号。

与 UDP 一样,校验和的计算需要加上「伪头部」。

连接建立

采用「3 次握手」方式建立连接。连接只能由客户端主动建立。


方向标志位SEQACK作用
第 1 次握手C \(\to\) SSYN随机数 \(x\)0请求发起连接
第 2 次握手S \(\to\) CSYN, ACK随机数 \(y\)\(x+1\)对第 1 次握手进行确认,允许连接
第 3 次握手C \(\to\) SACK\(x+1\)
\(y+1\)对第 2 次握手进行确认,连接建立

消息交互

通过三次握手建立连接后,双方可以进行全双工的通信。在上面的连接建立后,第一条消息的 SEQ、ACK 值为:


SEQACK说明
C \(\to\) S\(x+1\)\(y+1\)与它发送的第三次握手一致,因为服务器不会回复它的第三次握手,中间没有产生过新的消息,所以序号与上一次消息是一样的。
S \(\to\) C\(y+1\)\(x+1\)ACK 是 \(x+1\),表示希望客户端下一次发送的 SEQ 是 \(x+1\)(因为第三次握手的 ACK 段 的长度为零)

TCP 的序号是基于字节的:

  • 本次的 SEQ = 上次本机发送的段的 SEQ + 上次本机发送的段的长度

    • 单纯的 ACK 包,长度为零;

    • FIN / SYN 包,长度为 1。

  • 本次的 ACK = 希望下次收到对方的段的 SEQ。

重传

针对每个报文段设置一个计时器,当发送后过了一段时间还没有收到 ACK 即认为丢包,进行重传。超时时间是通过测量 RTT 进行加权得到的。

如果发送方连续收到同一段的三次 ACK,认为此段的下一段丢包,直接重传(快速重传)。

流量控制

接收方通过段首的窗口大小字段 rwnd 来告诉发送方自己最大接收能力。发送方「已经发送但没有收到 ACK」的数据大小不超过 rwnd

拥塞控制

发送方需要知道 rwnd 即接收方的窗口大小和 cwnd 即当前网络的拥塞程度,并取小者作为自己的发送窗口大小。

  • 慢开始算法:TCP 刚建立时,cwnd 设为 1。此后每完成一次发送 1 个 MSS,就加上 1。直到 cwnd 达到 ssthresh

    如果每次发送都用尽发送窗口(即「发送方有足够多的数据发送」),那么直观上的表现就是:每经过 1 个 RTT,cwnd 就会翻倍。

  • 拥塞避免算法:cwnd 达到 ssthresh 后,每经过 1 个 RTT 再将 cwnd 加上 1,而不是每收到 1 个 MSS 的确认就加 1。

  • 拥塞发生:当出现丢包时,将 ssthresh 设为此时 cwnd 的一半,然后 cwnd 重新置为 1。

连接断开

采用「4 次挥手」方式断开连接。双方都可以主动断开连接。