1、TCP 提供面向连接的可靠性传输。一、TCP 首部TCP 首部包含在 ip 首部中:Ip 首部 Tcp 首部 Tcp 数据TCP 首部格式:16 位源端口号 16 位目的端口号32 位序号32 位确认序号4 位首长保留(6位)URGACKPSHRSTSYNFIN16 位窗口大小16 位检验和16 位紧急指针选 项数 据(1) 端口号:用来区分发送端与目的端的应用进程。(2) 序号:指的是数据部分第一个字节在整个字节流当中的位置、序号。例如:序号为 x,数据部分的长度为 L则报文序号为 x,下一个报文序号为 x+L(3) 窗口大小:窗口大小为字节数,最大为 65535,这个值是接收方期望接收的字
2、节数(4) 检验和:检验和覆盖整个 TCP 段,TCP 首部、TCP 数据。这是个强制字段,由发送方计算,由接收方校验。(5) 紧急指针与带外数据:带外数据位于数据部分的开始,不在数据缓冲区中排队,当收到带外数据时,TCP 应将带外数据立即交给应用进程。紧急指针指向带外数据的最后一个字节。(6) 选项:一般为最大报文长度(MSS) ,接收方允许接收方允许接收的最大字节数。(7) 控制字段:说明了报文的类型、流控、连接建立和终止URG:紧急指针RST:连接复位SYN:连接建立FIN:链接终止ACK:当此位置 1 时,序号字段有效,报文带确认信息PSH:接收方应尽快将这个报文交给应用层二、TCP
3、一些概念一)TCP 确认机制带重传的肯定确认。接收方收到数据后,向源站返回 ACK 报文,五确认时,发送方应重传数据累计确认:(1) ACK 取值是接收方期望收到的下一个字节。(2)是对 ACK 以前的所有字节数据的确认。二)超时与重传机制发送方发送数据时,同时开启一个定时器,定时期满时,如果没有收到确认,重发数据,否则发送下一个数据。未确认数据包括:(1) 受损或丢失数据。(2) 确认的 ACK 丢失了。当接收方收到数据,但发送方没有收到确认信息,也认为没有正确的收到数据。三)滑动窗口窗口:发送方发送数据量的大小,即发送方在收到确认前,其发送缓冲区可以发送数据的大小。滑动:随着确认的不断到达
4、,窗口也不断向后移动,根据 ACK,确认滑动的大小。三、TCP 连接的建立与关闭一)TCP 连接建立TCP 连接建立需要经过三次握手(1) 请求端发送一个 SYN 段,指明客户端打算连接服务器的端口(2) 服务器发回包含服务器的初始序号的 SYN 报文段作为应答。同时将确认序号设置为客户端的序号 ISN+1,因为 SYN 占用一个序号。(3)客户必须将确认序号设置为服务器的 ISN+1,对服务器的 SYN 报文段进行确认。通过这三个报文段,TCP 建立连接。二)TCP 连接关闭TCP 连接关闭需要经过四次握手(1) 首先进行关闭的一方发送第一个 FIN,执行主动关闭。(2) 另一方收到 FIN
5、 时,发回一个 ACK,确认序号为 FIN+1,接着执行被动关闭(3) 服务器执行关闭时,发送一个 FIN。(4) 客户必须对这个 FIN 进行确认,确认序号为接受的 FIN+1经过这四个报文段,TCP 连接关闭。TCP 处于半关闭状态时,允许连接的一端在结束他的发送后还能接受来自另一端的数据的能力。复位报文段:当连接请求到达时,目的端口没有进程正在听,对于 UDP 来说是发送一个 IGMP 的端口不可达的差错。而 TCP 则使用复位报文段。异常终止一个连接:(1)丢弃任何待发数据,立即发送复位报文段; (2)RST 的接收方区分另一端执行的是异常关闭还是正常关闭。RST 报文段中包含一个序号
6、和一个确认序号。RST 报文不会导致另一端产生任何响应,另一端根本不做任何确认。收到 RST 的一方将终止该连接,并通知应用层连接复位。半打开连接:如果一方已经关闭或异常终止连接而另一方不知道,这样的 TCP 称为半打开。四、TCP 交互数据流每一个交互按键都会产生一个数据分组,每次从客户端传到服务器的是一个字节的按键(而不是一行) 。换句话说,对于交互数据,TCP 是一个字节一个字节的发送。而服务器收到数据后,要回显字符。这样就会有四个报文段产生。(1) 来自客户端的交互按键(2) 来自客户端的按键确认(3) 来自服务器的交互按键的回显(4) 客户对回显信息的确认通常 TCP 在接收到数据时
7、,并不是立即发送 ACK,相反,推迟发送,以便将 ACK 与数据一起发生(数据捎带 ACK) 。绝大多数实现采用的延时为 200ms,也就是说 TCP 将以最大 200ms 的延时等待是否有数据一起发送。五、Nagle 算法客户如果每次只发送一个字节的数据到服务器,这样就产生了 41 字节的分组。20 字节的 IP 首部,20 字节的 TCP 首部,1 字节的数据。这些小分组在广域网中很容易产生拥塞出现。Nagle 算法要求,一个 TCP 连接上最多只有一个未被确认的未完成的小分组,在该分组的确认没有到达前不能发送其他的小分组。相反,TCP 收到这些少量的分组,并在确认到来时以一个分组的方式发
8、送出去。该算法是自适应的:确认到达的越快,数据就发送的越快。六、慢启动TCP 通过观察新分组进入网络的速率应该与另一端返回确认的速率相同而进行工作。慢启动为发送方增加一个窗口:拥塞窗口,记为 cwnd。当与另一个网络主机建立连接时,拥塞窗口被初始化为 1 个报文段(即另一端通告报文段的大小) ,每收到一个 ACK,拥塞窗口就增加一个报文段(cwnd 以字节为单位,但是慢启动以报文段大小为单位进行增加) 。发送方取拥塞窗口与通告窗口的最小值作为发送上限。拥塞窗口时发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。发送方开始时发送一个报文段,然后等待 ACK,当收到 ACK 后,拥塞窗口从
9、 1 增加到 2,即可以发送两个报文段。当收到这两个报文段的 ACK 时,拥塞窗口增加为 4。在某个点上可能达到互联网的容量,于是中间路由器开始丢弃分组。这就通知发送方拥塞窗口开得过大。TCP 的超时和重传机制对拥塞窗口起作用。七、拥塞避免算法慢启动算法是一个在连接上发起数据流的方法。但有时会达到中间路由器的上限,此时分组被丢弃。拥塞避免算法是处理丢失分组的方法。该算法假定由于分组受损引起的丢失是非常少的(远小于 1%) ,因此分组丢失就意味着在源主机与目的主机之间的某处网络上发出了拥塞。有两种分组丢失的指示:发送超时和收到重复的确认。拥塞避免算法和慢启动算法是两个目的不同、独立的算法,但是当
10、拥塞发生时,我们希望降低分组进入网络传输的速率,于是可以调用慢启动算法。拥塞避免算法和慢启动算法需要对每个连接维持两个变量:一个拥塞窗口 cwnd 和一个慢启动门限 ssthresh。(1) 对一个给定连接,初始化 cwnd 为一个报文段,ssthresh 为 65535 字节(2) TCP 输出不能超过 cwnd 和接收方通告窗口的大小,拥塞避免是发送方使用的流量控制,而通告窗口是接收方进行的流量控制。前者是发送方感受到网络拥塞的估计,后者则与接收方在该连接上可用换成的大小有关。(3)当拥塞发生时,ssthresh 被设置为当前窗口大小的一半(cwnd 与接收方通告窗口大小的最小值,但最少为
11、 2 个报文段) ,如果是超时引起了拥塞,则 cwnd 被设置为 1 个报文段(这既是慢启动) 。(4)当新的数据被对方确认时,就增加 cwnd,但增加的方法依赖于我们是否进行慢启动或拥塞避免,如果 cwnd 小于或等于 ssthresh,则正在进行慢启动,否则正在进行拥塞避免。八、快速重传与快速恢复算法在收到一个失序的报文段,TCP 立即需要产生一个重复的 ACK,这个重复的 ACK 不应该被迟延。该重复的 ACK 报文段的目的在于让对方知道收到一个失序的报文段,并告诉对方希望收到的报文段。由于不知道一个重复的报文段是由一个丢失的报文段引起的,还是由于仅仅出现了几个报文段重新排序,因此必须接
12、收到等待少量重复的 ACK 的到来。假如只是一些报文段的重新排序,则在重新排序的报文段被处理产生一个新的 ACK 之前,只可能产生 12 个重复的 ACK,如果一连收到 3 个或 3 个以上的重复 ACK,就非常有可能是一个报文段丢失了。于是重传丢失的报文段,而无需等待定时器溢出,这就是快速重传。接下来执行拥塞避免算法,就是快速恢复算法。九、IGMP 差错TCP 能够遇到的最常见的 IGMP 差错就是源站抑制、主机不可达、网络不可达。对差错处理:(1) 一个接收到的源站抑制引起拥塞窗口 cwnd 被置为 1 个报文段大小来发去慢启动,但是慢启动门限 ssthresh 没有变化,所以窗口将打开直
13、至他或者开放所以的通路或者发生了拥塞。(2) 一个接收到的主机不可以或网络不可达实际上都被忽略,因为这两个差错都被认为是短暂现象。这有可能是由于中间路由器被关闭而导致选路协议要花费数分钟才能稳定到另一个替换路由。在这个过程中就可能发生这两个 ICMP 差错中的一个,但是连接并不必被关闭。相反,TCP 试图发送引起该差错的数据,尽管最终有可能会超时。十、重新分组当 TCP 超时并重传时,它并不一定重传同样的报文段。相反,TCP 允许进行重新分组而发送一个较大的报文段,这将有助于提高性能(当然,这个较大的报文段不能超过接收方声明的 MSS) 。这在协议中是允许的,因为 TCP 是使用字节序号而不是
14、报文段序号来进行识别它所要发送的数据和进行确认。十一、坚持定时器TCP 通常让接收方指明希望从发送方接受的数据字节数(窗口大小)来进行流量控制。如果窗口为 0,将阻止发生数据,直到窗口变为 0 为止。ACK 的传输并不可靠,也就是说 TCP 不对 ACK 进行确认,TCP 只确认那些含有数据的 ACK 报文段。如果一个确认丢失了,则双方就有可能因为等待对方而连接终止:接收方等待接收数据,而发送方等待确认。为了防止这样的死锁,发送方使用一个坚持定时器来周期性的向接收方查询,以便发现窗口是否已经增大,这些从发送方发出的报文称为窗口查询。通告窗口为 0 时,客户停止发生任何数据,这就引起客户设置坚持
15、定时器,如果在该定时器到时,客户还没有接收一个新窗口更新,他就探查这个空窗口以决定窗口更新是否丢失。当定时器时间到时,就发送窗口查询,在收到应答后,定时器被重启。十二、保活定时器在一个客户与服务器的 TCP 连接中,中间路由器可以崩溃或重启,但只要两个连接中的主机不被关闭或重启,该链接依然存在。在大多数情况下,服务器需要知道客户端是否崩溃或关机或重启。保活功能是为服务器提供的,服务器的应用程序需要知道客户端是否正常,以便可以代表客户端使用数据。如果一个给定链接在两小时没有任何动作,则服务器就向客户端发送一个探查的报文段,客户必须处于一下 4 个状态之一。1) 客户机依然正常运行,并从服务器可达
16、。客户的 TCP 响应正常,而服务器也知道对方是正常工作的。服务器将保活定时器复位。如果在两个小时内定时器时间到来之前有数据交换、通信,则服务器在交换数据后的未来 2 小时复位保活定时器。2) 客户机关闭或重启或崩溃。客户机的 TCP 没有响应,服务器将不能收到探查响应,并在 75s 后超时,如果服务器没有收到响应,就认为客户机已经关闭或终止连接。3) 客户主机崩溃并重启。这是服务器收到一个响应,但是这个响应是一个复位,是的服务器终止连接。4) 客户机正常运行,但是服务器不可达。这与状态 2 相同,因为 TCP 不能区分状态 4 与状态 2。服务器不用关注客户主机被关闭或重启的状态(不是崩溃) ,当关闭或重启时,TCP 向服务器发送一个 FIN,收到 FIN 的服务器向应用程序发送文件结束符,使服务器检测到这种情况。在第一种情况,服务器的应用程序没有感觉到保活查询的发生,TCP 层负责这一切。这个过程对应用程序都是透明的,直到 2、3、4 的情况发生。在这三种情况下,服务器的应用程序将收到来自它的 TCP 的差错报告。在第二种情况下,差错时诸如 “连接超时”之类的信息。第三种情况,则为“链接被复位” 。第四种情况下,可以为超时链接,也可根据示范收到与链接相关的 ICMP 的差错返回其他差错。