概述
- TCP是一个面向连接的协议。无论哪一方向另一方发送数据前,都必须先在双方之间建立一条连接。
- 这种两端间连接的建立与无连接协议如UDP不同。一端使用UDP向另一端发送数据报时,无需任何预先的握手。
建立连接
- 发送第一个SYN的一端将执行主动打开(active open)。接收这个SYN并发回下一个SYN的另一端执行被动打开(passive open)。
- 当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号。SYN随时间而变化,因此每个连接都将具有不同的SYN。RFC793指出SYN可以看做是一个32比特的计算器,每4ms加1.这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。
- ack:ack的值表示期望对方下一次发的报文从ack的值开始。
连接终止协议
- 建立一个连接需要三次握手,而终止一个连接要经过4次挥手。这由TCP的半关闭(half-close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独第进行关闭。这原则就是当一方完成它的数据发送任务后就发送一个FIN来终止这个方向连接。当一端接收到一个FIN,它必须通知应用层另一端已经终止了那个方向的数据传送。发送FIN通常是应用层进行关闭的结果。
- 收到一个FIN只意味在这一方向上没有数据流动。一个TCP连接在收到一个FIN后仍能发送数据。而这对利用半关闭的应用来说是可能的,尽管在实际应用中只有很少的TCP应用程序这样做。
- 首先进行关闭的一方(即发送第一个FIN)将执行主动关闭,而另一方(收到FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。
- 关闭一边的连接其实只是关闭的一方不在发送带数据的包,ack还是可以发送的。
连接建立的超时
- 在这个输出中有趣的一点是客户间隔多长时间发送一个SYN,试图建立连接。第2个SYN与第1个的间隔是5.8s,而第3个与第2个的间隔是24s。
- 作为一个附注,这个例子是运行38分中后客户机启动tcp连接。这对应初始版本号为291008001(38606400 * 2)。另外,因为这是系统启动后的第一个TCP连接,因此客户的端口号是1024(0-1023是知名端口号)。
- tcp报文超时重传机制,第一次6s,第二次24秒。
最大报文端长度
- 在有些书中,将它看作可协商 选项。它并不是任何条件下都可协商。当建立一个连接时,每一方都有用于通告它期望接收的MSS选项(MSS选项只能出现在SYN报文段中)。如果一方不接收来自另一方的MSS值,则MSS就定为默认值536字节。
- 一般来说,如果没有分段发送,MSS还是越大越好(这也并不总是正确)。报文段越大允许每个报文段传送的数据就越多,相对IP和TCP首部有更高的网络利用率。当TCP发送一个SYN时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到了一个连接请求,它能将MSS值设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度。对于一个以太网,MSS值可达1460字节。使用IEEE 802.3封装,它的MSS可达1452字节。
- 如果目的IP地址为“非本地的(nonlocal)”,MSS通常的默认值是536。而区分地址是本地还是非本地是简单的,如果目的IP地址的网络号与子网号都和我们的相同,则是本地的;如果目的IP地址的网络号与我们的完全不同,则是非本地的;如果目的IP地址的网络号与我们的相同而子网号与我们的不同,则可能是本地的,也可能是非本地的。大多数TCP实现版都提供了一个配置选项,让系统管理员说明不同的子网是属于本地还是非本地。这个选项的设置将确定MSS可以选择尽可能的大(达到外出接口的MTU)或是默认值536。
TCP的半关闭
- TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓的半关闭。正如我们早些时候提到的只有很少的应用程序使用它。
- 为什么要有半关闭?一个例子是Unix中的rsh命令,它将完成在另一个系统上执行一个命令。命令:% rsh bsdi sort < datafile
- 将在主机bsdi上执行sort排序命令,rsh命令的标准输入来自文件datafile。rsh将在它与在另一个主机上执行的程序间建立一个TCP连接。rsh的操作很简单:它将标准输入(datafile)复制给TCP连接,并将结果从TCP连接中复制给标准输出(我们的终端)。
- 没有半关闭,需要其他的一些技术让客户通知服务器客户端已经完成了它的数据传送,但仍然要接收来自服务器的数据。使用两个TCP连接也可作为一个选择。
TCP的状态变迁图
|