网络协议与分析课后习题 下载本文

TCP input FSM启动定时输出TCP 定时模块tcpswitch[]tcpdemuxtcpcksumnetstart创建tcpinptcpnet2hpreceive获取报文段OS内部数据通道发送报文段psendtcpoktcp_inIP模块local_out 图9-2 TCP软件输入模块结构

从图中可以看到,整个TCP输入部分以输入进程tcpinp()和输入状态机为中心。输入进程在网络初始化时由函数netstart()创建。当IP软件通过环回接口将数据包交给TCP软件时,TCP软件会调用tcp_in()函数将相关的TCP报文段放入系统内部的数据通道中。随后,输入进程会从中取出相应的报文段,并依次调用tcpcksum()函数、tcpnet2h()函数、tcpdemux()函数和tcpok()函数计算报文段的检验和,转换首部字节序,根据端口号对其进行解复用并判断报文段的合法性。此后,输入进程会通过函数指针数组tcpswitch[]根据连接的当前状态为报文段选择合适的状态处理函数。在报文段处理期间,TCP软件可能会通过TCP定时模块为当前报文段启动一个输出事件。

netstart创建创建tmset设定TCP 定时器到期tcptimerpsend发送消息OS内部消息队列获取消息preceivetcpouttcpinpTCP input FSMtcpackedtcposwitch[]tcpresettcppersisttcprexmttcpxmittcpidletcpsendtcphowmuchtcpsndlentcph2netIP模块 图9-3 TCP软件输出模块结构

图9-3描绘了TCP定时模块和输出模块的函数调用关系图。从图中我们可以看到,TCP的输出主要有两种情况:第一种情况是在输入处理过程中出错时,TCP软件会通过tcpreset()函数发送RST报文段终止连接。这种情况的处理比较简单,tcpreset()函数可以直接调用IP模块发送RST报文段。另一种情况下TCP输入模块会调用定时模块提供的tmset()函数注册一个定时输出事件。TCP定时进程tcptimer会维护已注册的事件,当一个定时事件到期后,进程tcptimer会通过系统内部的消息通道向TCP输出进程tcpout发送一个消息。tcpout收到消息后会通过函数指针数组tcposwitch[]根据当前状态选择合适的状态处理函数。tcppersist()函数、tcprexmt()函数、tcpxmit()函数和tcpidle()函数分别对应了TCP输出状态机中的四个状态处理函数。如果此时TCP软件需要发送一个报文段,输出状态机会调用tcpsend()函数,tcpsend()函数会调用tcpsndlen()函数和tcpnet2h()函数计算发送数据的长度并转换报文段的首部字节序。

最后我们可以看到,进程tcptimer和tcpout都是在网络初始化时由函数netstart()创建的。

tcpdodattcpdataTCP input FSMtcpswindowTCP output FSMtcpostatetcpsmsstcpoptstcpinptcpackedtcprtttcpgetdatatcpouttcpackittcprwindowtcpsendtcprmssIP模块 图9-4 TCP控制模块结构图

在TCP软件进行输入和输出处理时,除了处理基本数据,软件还要还要进行流量控制、差错控制和拥塞控制。图9-4描绘了这些机制在软件中是如何被各个模块调用的。从图中可以看到,TCP输入进程在处理一个报文段时会调用tcpopts()函数进行选项处理,

tcpopts()函数又会调用tcpsmss()函数设定发送时的最大报文段长度。当报文段被交付给输入状态机后,TCP软件会通过tcpdata()函数将报文段中的数据放入输入缓冲区中,随后又会通过tcpdodat()函数处理缓冲区中的数据。同时,输入状态机还会调用

tcpacked()函数生成一个ACK报文段。tcpacked()函数既有可能发送一个包含传输数据的ACK报文段,也有可能通过tcpackit()函数回复一个纯ACK报文段。此外tcpacked()函数还会通过tcprtt()函数计算往返延时并通过tcpostate()函数改变输出状态机的状态。此外,输入状态机还可能根据收到报文段中的确认号调用

tcpswindow()函数设定发送窗口的大小。

当上层软件调用tcpgetdata()函数获取接收缓冲区的数据时,tcpgetdata()函数会调用tcprwindow()函数重新计算接收窗口的大小。而在TCP输出状态机调用tcpsend()函数发送一个报文段时也会调用tcprwindow()函数获取当前窗口通告值。此外,tcpsend()函数还会调用tcprmss()函数计算当前可接收的最大报文段长度。

2、简述TCP输入状态机

参考P178页的图9-6 TCP输入状态机总共那个有11个状态。下面是TCP从连接到终止过程的状态转移。 1. 正常状态转换

服务器端首先执行 LISTEN 原语进入被动打开状态( LISTEN ),等待客户端连接; 当客户端的一个应用程序发出 CONNECT 命令后,本地的 TCP 实体为其创建一个连接记录并标记为 SYN SENT 状态,然后给服务器发送一个 SYN 报文段;

服务器收到一个 SYN 报文段,其 TCP 实体给客户端发送确认 ACK 报文段同时发送一个 SYN 信号,进入 SYN RCVD 状态;

客户端收到 SYN + ACK 报文段,其 TCP 实体给服务器端发送出三次握手的最后一个 ACK 报文段,并转换为 ESTABLISHED 状态;

服务器端收到确认的 ACK 报文段,完成了三次握手,于是也进入 ESTABLISHED 状态。 在此状态下,双方可以自由传输数据。当一个应用程序完成数据传输任务后,它需要关闭 TCP 连接。假设仍由客户端发起主动关闭连接。

客户端执行 CLOSE 原语,本地的 TCP 实体发送一个 FIN 报文段并等待响应的确认(进入状态 FIN WAIT 1 );

服务器收到一个 FIN 报文段,它确认客户端的请求发回一个 ACK 报文段,进入 CLOSE WAIT 状态;

客户端收到确认 ACK 报文段,就转移到 FIN WAIT 2 状态,此时连接在一个方向上就断开了;

服务器端应用得到通告后,也执行 CLOSE 原语关闭另一个方向的连接,其本地 TCP 实体向客户端发送一个 FIN 报文段,并进入 LAST ACK 状态,等待最后一个 ACK 确认报文段; 客户端收到 FIN 报文段并确认(也就是发一个ACK),进入 TIMED WAIT 状态,此时双方连接均已经断开,但 TCP 要等待一个 2 倍报文段最大生存时间 MSL ( Maximum Segment Lifetime ),确保该连接的所有分组全部消失,以防止出现确认丢失的情况。当定时器超时后, TCP 删除该连接记录,返回到初始状态( CLOSED )。

服务器收到最后一个确认 ACK 报文段,其 TCP 实体便释放该连接,并删除连接记录,返回到初始状态( CLOSED )。

3、总结TCP中存在的差错控制、拥塞控制和流量控制机制。

TCP的差错控制: TCP的差错控制包括:检测受到损伤的数据段,丢失的数据段,失序的数据段和重复的数据段,还包括检测出差错后的纠错机制。

TCP中的差错检验是通过三种简单方式完成的:校验和、确认、超时。 校验和:每一个数据段都包括校验和字段,用来检测受到损伤的数据段。

确认:TCP使用确认的方式来证实收到了某些数据段,它们已经无损伤的到达了目的地。 超时:若一个报文在超时前未被确认,则被认为是受到损伤或已丢失。 1、受损的数据段,被丢失。

2、丢失的数据段,不认为接收过。

3、重复的数据段,直接丢弃重复的数据段。 4、失序的数据段,对失序的数据不确认。 5、丢失的确认,TCP使用累计确认系统。

相关字段为tcb_suna:send unacked 、tcb_snext:send next、tcb_slast:sequence of FIN, if TCBF_SNDFIN、tcb_rexmt: retransmit timeout value 、tcb_rexmtcount:number of rexmts sent,体现在

tcpxmit():handle TCP output events while we are transmitting tcpackit():generate an ACK for a received TCP packet tcpacked():handle in-bound ACKs and do round trip estimates tcprexmt():handle TCP output events while we are retransmitting 等函数中;

拥塞控制:慢启动,拥塞避免算法