本文处理ACK标志,更新窗口信息,处理URG标志及报文段中携带的所有数据,最后处理FIN标志,如果需要,则调用
tcp_output。
1.完成被动打开和同时打开
本节介绍如何处理SYN_RCVDz状态下收到的ACK报文段。这也将完成被动打开,或者是同时打开及自连接的连接建立
过程。
1.验证收到的ACK。
2.查看窗口大小选项。
3.向应用进程提交队列中的数据。
2.快速重传和快速恢复的算法
快速重传算法用于连续出现几次(一般是3次)重复ACK时,TCP认为某个报文已丢失并且从中推断出丢失报文段的起始
序号,丢失报文段被重传。RFC 1122中提到了这一算法,建议TCP收到乱序报文段后,立即发送ACK。
快速恢复算法认为采用快速重传算法之后(即丢失报文段已重传),应执行拥塞避免算法,而非慢启动。这样,如果拥塞
不严重,还能保证较大的吞吐量,尤其窗口较大时。
Net/3同时实现了快速重传和快速恢复算法。
3.ACK处理
下面继续处理ACK。
1.调整拥塞窗口。
2.检查ACK的有效性。
3.计算确认的字节数。
4.更新RTT测算值。
5.是否确认了所有已发送数据。
6.存在未确认的数据。
7.更新拥塞窗口。
8.从发送缓存中删除已确认的字节。
9.唤醒等待发送缓存的进程。
10.在FIN_WAIT_1状态时收到了ACK。
11.设定FIN_WAIT_2定时器。
12.在CLOSING状态收到了ACK。
13.在LAST_ACK状态收到ACK。
14.在TIME_WAIT状态收到了ACK。
4.更新窗口信息
1.是否需要更新发送窗口。
2.更新变量。
5.紧急方式处理
TCP输入处理的下一部分是URG标志置位时的报文段。
1.是否需要处理URG表示。
2.忽略超出的紧急指针。
3.计算收到的紧急指针。
4.向应用进程通告TCP的紧急方式。
5.从正常的数据流中提取带外数据。
6.如果不处于紧急方式,调整接收紧急指针。
6.处理已接收的数据
tcp_input接着提取收到的数据(如果存在),将其添加到插口接收缓存,或者放入插口的乱序重组队列中。
7.FIN处理
tcp_input的下一步,处理FIN标志。
1.处理收到的第一个FIN。如果接收报文段FIN置位,并且是连接上收到的第一个FIN,立即发送ACK。
2.SYN_RCVD和ESTABLISHED状态。如果连接处与SYN_RCVD和ESTABLISHED状态,收到FIN后,新状态为CLOSE_WAIT.
3.FIN_WAIT_1状态。因为报文段的ACK处理已结束,如果处理FIN时,连接处于FIN_WAIT_1状态,意味着连接两端同时关闭
连接---两端发送的两个FIN在网络中交错。连接进入CLOSING状态。
4.FIN_WAIT_2状态。收到FIN将使连接进入TIME_WAIT状态。当FIN_WAIT_1状态收到携带ACK和FIN的报文段时,尽管连接
直接从FIN_WAIT_1转移到TIME_WAIT状态,但是处理ACK时,连接实际已进入FIN_WAIT_2状态。此处的FIN处理再将连接
转移到TIME_WAIT状态。因为ACK在FN之前处理,所以连接总会经过FIN_WAIT_2状态,尽管是短暂性的。
5.启动TIME_WAIT定时器。
6.TIME_WAIT状态。如果在TIME_WAIT状态时收到FIN,说明这是一个重复报文段,启动TIME_WAIT定时器,时限等于两倍的
MSL。
8.最后的处理
1.SO_DEBUG插口选项。如果选用了SO_DEBUG插口选项,则向内核的环形缓存中添加记录。
2.调用tcp_output。
3.dropafterack。
4.dropwithreset。
5.RST报文段的序号和确认序号。
6.拒绝连接。
7.释放临时创建的插口。
8.丢弃(不带ACK或RST)