(参考文献)TCP/IP详解,卷1:协议
TCP的服务
尽管TCP和UDP都使用相同的网络层(IP层),TCP却向应用层提供与UDP完全不同的服务。TCP提供一种面向连接的、可靠的字节流服务。
面向连接意味着,两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。TCP通信,本质上是两个线程之间的通信(客户端与服务端);而TCP连接的建立,本质上是可以说是服务端和客户端通过交换信息,各端都建立了一个进程拥有完整地理信息的进程或者线程(即这个线程或进程知道目的端ip地址和目的端端口号)。
在一个TCP连接中,仅有两方进行彼此通信。TCP通过以下方式来提供可靠性:
TCP对字节流的内容不做任何解释,他只管将报文段接收和排序然后交给应用层。TCP不知道传输的数据字节流是二进制数据还是ASCII字符,对字节流的解释有TCP连接双方的应用层解释。
TCP的首部
TCP数据被封装在一个IP数据报中,如下:
如下,是TCP首部的数据格式,如果笔记选项字段,他通常是20个字节
每个TCP都包含源端和目的端的端口号,用于寻找发端和接收端应用进程。这两个值加上IP地址中的源端IP地址和目的端IP地址可以唯一确定一个TCP链接。
一个IP地址和一个端口号也称作一个插口或叫套接字(socket)。一个插口(包含客户端IP地址,客户端端口号,服务器IP地址和服务器端口号)可以唯一确定互联网络中每个TCP链接的双方。
TCP首部中有6个标志比特。他们中的多个可同时被设置为1 。
URG 紧急指针有效
ACK 确认序号有效
PSH 接收方应该尽快将这个报文交给应用层
RST 重建连接
SYN 同步序号用来发起一个连接
FIN 发端完成发送任务
TCP建立连接的三次握手:
1)请求端(通常称为客户)发送一个SYN段来指明客户打算连接的服务器的端口,以及初始序号(ISN,在这里假设为1415531521)。这个SYN段为报文段1 。
2)服务器发回包含服务器的初始序号的SYN报文段(报文段2)作为应答,同时将确认序号设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。
3)客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认(报文段3)。
这三个报文段完成连接的建立。这个过程也称为3次握手。
发送第一个SYN的一端将执行手动打开。接收到这个SYN并发回下一个SYN的另一端执行被动打开。
当一端为建立连接而发送它的SYN时,他为连接选择一个初始序号(ISN)。ISN的选择随时间变化,因此每个连接都具有不同的ISN。RFC 793[Postel 1981c]指出ISN可看做是一个32比特的计数器,每隔4ms加1.
TCP建立连接终止的四次握手:
建立一个连接需要3次握手,而终止一个连接则需要4次握手。这由于TCP的半关闭造成的。TCP连接是全双工的(即两个方向上可以同时传输数据),因此,每个方向必须单独的进行关闭。原则就是:当一方完成它的数据发送任务后,就会发送一个FIN来终止这个方向的连接。发送FIN通常是应用层进行关闭的结果。
收到一个FIN只意味着在在这个方向上没有数据的流动。一个TCP连接收到一个FIN后任然能发送数据。而这对于利用半关闭的应用来说是可能的尽管应用程序能够利用这种半关闭特性,但在实际应用中只有很少的TCP应用程序这么做。
首先进行关闭的一方(及发送第一个FIN)将执行主动关闭,而另一方(收到这个FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。
当服务器收到这个FIN,他发回一个ACK,确认序号为收到的序号加1 。和SYN一样,一个FIN将占用一个序号。同时TCP服务器还向应用程序(客户)传输一个结束符。接着这个客户程序就关闭他的TCP连接,导致他的TCP端发送一个FIN,客户必须发回一个确认,并将确认序号设置为收到序号加1 。
连接通常是由客户端发起的,这样第一个SYN从客户传到服务器。每一段都能主动关闭这个连接(即首先发送FIN)。然而,一般有客户端决定何时终止连接,因为客户进程通常由用户交互控制,用户会键入如“quit”一样的命令来终止进程。
TCP的半关闭
TCP提供了连接的一端在结束他的发送后还能结束来自另一端数据的能力。这就是所谓的半关闭(只有很少的应用会使用到半关闭)。
TCP的半打开连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这种TCP连接成为半打开的。任何一端的主机异常都可能产生这种情况。只要不在半打开连接上传输数据任然处于连接状态的一方就不会坚持到另一方已经出现异常。
半打开连接的另一个常见原因是当客户主机突然掉电而不是正常的结束客户应用程序后在关机。