TCP协议梳理

1. TCP数据段格式
TCP数据段的格式如下图所示,其中每一格代表一个比特位。


1.1 Source Port和Destination Port
为了让同一主机上的多个进程可以同时使用TCP层,定义端口,分配给每个需要使用TCP的进程。
1.1.1 Socket和Connection
  • Internet层地址加上TCP层端口确定一个Socket
  • 两端的两个Socket唯一确定一条Connection

1.2 Sequence Number
给出数据部分第一个字节的Sequence Number,由此TCP传输的每个字节都拥有Sequence Number编号。

1.2.1 Initial Sequence Number(ISN)
一条连接由1对Socket唯一确定,为保证新连接不会收到之前已终止的连接,但仍在网络中游荡的老TCP段的影响,TCP在创建连接时,需要进行ISN(Initial Sequence Number)的商定,ISN是连接中第一个数据字节的Sequence Number:
1) A --> B SYN my sequence number is X
2) A <-- B ACK your sequence number is X
3) A <-- B SYN my sequence number is Y
4) A --> B ACK your sequence number is Y


ISN的确定策略:
  • 若记录了上次连接发送的最大sequence number,则设定为上次连接发送的最大sequence number+1
  • 若失去了上次连接发送的最大sequence number,则随机选取或选用时间戳,并在连接建立初期保持MSL(Maximum Segment Lifetime)时间段的静默


1.3 Acknowledgment Number
指明对连接对端数据的确认,意为sequence number  < Acknowledgment Number的字节都已正确接收。

1.4 Data Offset
指明数据部分的开始位置。

1.5 Reserved
必须为0.

1.6 6比特控制字段
分别为以下6比特:
  • URG: 只有当该比特为1时,后续的Urgent Pointer字段才有效
  • ACK:只有当该比特为1时,前面的Acknowledgment字段才有效
  • PSH: 实现应当将数据段立即发送到对端
  • RST: Reset the connection
  • SYN: 说明当前数据段是SYN数据段,用于建立连接时同步两端的Sequence Number
  • FIN: 说明当前数据段是FIN数据段,用于关闭当前连接

1.7 Window
表明该数据段发送者当前窗口大小,即从acknowledgment字段开始最多接收的字节数。通常由接收缓冲区大小决定。

1.8 Checksum
校验和。

1.9 Urgent Pointer
This field communicates the current value of the urgent pointer as a positive offset from the sequence number in this segment. The urgent pointer points to the sequence number of the octet following the urgent data. This field is only be interpreted in segments with the URG control bit set.

1.10 Options
可选选项。



2. 连接的管理

2.1 连接的建立
连接的建立也称连接的同步过程是,主要任务是同步两端的Sequence Number,Sequence Number一旦同步,两端就可以基于此开始可靠的数据传递。典型的“三次握手”即如下图所示:


连接建立过程也可能出现非典型情况和异常情况,只要双方能完成最终Sequence Number同步,即可完成连接建立。例如,下图所示非典型的两端同时发起连接的情况:


2.2 连接的重置
连接重置用于在发现连接状态失去同步或者异常情况下立即关闭连接:
  • 当收到明显不属于当前连接的数据段时,应当向对端发送RST
  • 在无法确定属于上述情况时,RST不应当发送

2.2.1 RST的发送端逻辑
2.2.1.1 当连接处于CLOSED(连接不存在)状态时
  • 收到任何非RST数据段都应当回复RST
  • 如果收到的数据段包含ACK,RST以该ACK作为sequence number,否则sequence number设为0
  • RST的ACK字段设为收到数据段的sequence number加长度
  • 连接保持CLOSED状态


2.2.1.2 当连接处于非同步状态(LISTEN, SYN-SENT, SYN-RECEIVED)时
  • 当收到数据包ACK了还未发送的字节时,回复RST
  • 当安全性校验失败时,回复RST
  • 如果收到的数据段包含ACK,RST以该ACK作为sequence number,否则sequence number设为0
  • RST的ACK字段设为收到数据段的sequence number加长度
  • 连接保持CLOSED状态


2.2.1.3 当连接处于同步状态(ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT),时
  • 只有当安全性检验失败时发送RST
  • 如果收到的数据段包含ACK,RST以该ACK作为sequence number,否则sequence number设为0
  • 如果收到不合理的数据段(诸如sequence number落在窗口外,或者是不合理的ACK),不发送RST,而仅发送一个空的ACK数据段包含当前的send-sequence number,并以下一个期望的字节作为ACK,连接状态不变

2.2.2 RST的接收端逻辑
  • 除了SYN-SENT状态,落在接收窗口中的RST都认为合法
  • 处于SYN-SENT状态时,ACK了之前发送的SYN的RST认为合法

当收到合法的RST时:
  • 若当前处于LISTEN状态,忽略RST
  • 若当前处于 SYN-RECEIVED状态(之前处于LISTEN状态),则返回LISTEN状态
  • 当前处于其他状态时进入CLOSED状态


2.3 连接的关闭
关闭连接指的是关闭连接的发送通道,仍然可以接收数据。如果随后对端也关闭了连接,则双向连接完全关闭。

连接的关闭有三种情况:
  • 上层用户调用CLOSE主动发起连接关闭(向对端发送FIN数据段)
  • 收到来自对端的FIN数据段,即对端发起了连接关闭
  • 两端同时发起关闭连接

分别对应连接状态关闭的3条链路:




3. TCP接口
3.1 接口清单
具体的TCP实现应当向上层服务提供下列接口,及其对TCP连接状态机的影响。



3.2 Open调用
OPEN (local port, foreign socket, active/passive[, timeout] [, precedence] [,security/compartment] [, options])
返回值: local connection name

  • Open操作分为Active和Passive两种,Active即客户端模式,主动发起连接,Passive即服务器模式,被动等待客户端发起连接。Passive模式可以指定remote socket进行等待,或不指定,等待任意客户端连接
  • 创建新的TCB(transmission control block),并保存相关信息
  • Timeout指定数据被投递完成的最后时限,默认值5分钟。如果超过该时限还未成功则终止连接
  • 返回值local connection name与(local socket, remote socket)对等价
  • 若没有足够空间创建连接则返回"error: insufficient resources"


3.3 SEND调用
SEND (local connection name, buffer address, byte count, PUSH flag, URGENT flag [,timeout])

其中,
  • 若PUSH flag set,实现应立即发送该数据包。
  • 若URGENT flag set,实现应做紧急处理



3.3.1 若当前状态为: LISTEN
  • 若Open(passive)未指定remote socket,则返回 "error: foreign socket unspecified"。
  • 若Open(passive)指定了remote socket,则转换为Active,并发送SYN数据段。数据部分可以与SYN数据段一起发送或暂存发送缓冲区,待进入ESTABLISHED状态后再发送,若缓冲区空间不足,则返回"error: foreign socket unspecified"


3.3.2 若当前状态为: SYN-SENT、SYN-RECEIVED
数据进入发送缓冲区,待进入ESTABLISHED状态后再发送,若缓冲区空间不足,则返回"error: foreign socket unspecified"。

3.3.3 若当前状态为: ESTABLISHED、CLOSE-WAIT
发送数据,并捎带ACK。

3.4 RECEIVE调用
RECEIVE (local connection name, buffer address, byte count)
返回值:byte count, urgent flag, push flag


3.4.1 若当前状态为: LISTEN、SYN-SENT、SYN-RECEIVED
RECEIVE请求入队等待,直到进入ESTABLISHED状态再执行,若队列空间不足返回 "error: insufficient resources"

3.4.2 若当前状态为: ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2
若当前有足够数据则向用户返回。若当前无足够数据,则RECEIVE请求入队等待,若队列空间不足返回 "error: insufficient resources"。

3.4.3 若当前状态为: CLOSE-WAIT
若当前有足够数据则向用户返回。若已无数据,则将来也不会再有了,返回"error: connection closing"

3.4.4 若当前状态为: CLOSING、LAST-ACK、TIME-WAIT
返回 "error: connection closing"。

3.5 CLOSE调用
CLOSE (local connection name)

CLOSE调用的语义为,TCP的当前端没有更多的数据需要发送,可以关闭发送,但仍可以接收数据。

3.5.1 若当前状态为: LISTEN、SYN-SENT
  • 所有正在等待的SEND、RECEIVE请求返回"error: closing"
  • 进入CLOSED状态并返回


3.5.2 若当前状态为: SYN-RECEIVED
  • 若没有执行过任何SEND,则立即发送FIN,并进入FIN-WAIT-1状态
  • 若执行过SEND,则CLOSE请求入队,等待进入ESTABLISHED状态后执行


3.5.3 若当前状态为: ESTABLISHED
CLOSE请求入队,直到所有前序SEND执行完成后发送FIN,并进入FIN-WAIT-1状态.

3.5.4 若当前状态为: CLOSE-WAIT
CLOSE请求入队,直到所有前序SEND执行完成后发送FIN,并进入CLOSING状态.

3.6 ABORT调用
ABORT (local connection name)


3.6.1 若当前状态为: LISTEN、SYN-SENT
所有等待的SEND、RECEIVE请求返回"error: connection reset"并进入CLOSED状态.

3.6.2 若当前状态为: SYN-RECEIVED、 ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2 或者CLOSE-WAIT
  • 向对端发送RST
  • 所有等待的SEND、RECEIVE请求返回"error: connection reset"
  • 所有缓冲区数据段(包括重传数据段)应当尽快flush
  • 进入CLOSED状态

4. 超时的处理
超时分为三种:
  • 用户超时:无论连接处于何种状态,超过对上层用户提供的超时保障时,尽快清空所有队列,进入CLOSED状态,并返回"error: connection aborted due to user timeout"
  • 重传超时:无论连接处于何种状态,对于重传队列中的某个数据段,如果重传超时, send the segment at the front of the retransmission queue again, reinitialize the retransmission timer, and return.
  • TIME-WAIT超时:连接进入CLOSED状态

猜你喜欢

转载自chong-zh.iteye.com/blog/2357759
今日推荐