面向连接的运输:TCP
TCP依赖于可靠数据传输,其中包括差错检测、重传、累积确认、定时器以及用于序号和确认号的首部子弹。
TCP连接
TCP被称为是面向连接的,这是因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先相互“握手”,即他们必须相互发送某些预备报文段,以建立确保数据传输的参数。作为TCP连接建立的一部分,连接的双方都将初始化与TCP连接相关的许多TCP状态变量。
TCP协议只在端系统中运行,而不在中间的网络元素中运行,所以中间的网络元素不会维持TCP连接状态。
clientSocket.connection((serverName,serverPort)),客户端与服务端建立连接,客户端首先发送一个特殊的TCP报文段,服务器用另一个特殊的TCP报文段来响应,最后,客户再用第三个特殊报文段作为响应。这种连接建立过程常被称为三次握手。
TCP报文段结构
如图显示了TCP报文段的结构。与UDP一样,首部包括源端口号和目的端口号,它被用于多路复用/分解来自或送到上层应用的数据。另外,同UDP一样,TCP首部也包括检验和字段。
TCP报文段首部还包括下列字段:
1. 32比特的序号字段和32比特的确认号字段。这些字段被TCP发送方和接收方用来实现可靠数据传输服务。
2. 16比特的接收窗口字段,该字段用于流量控制。该字段用于指示接收方愿意接受的字节数量。
3. 可选与变长的选项字段,该字段用于发送方与接收方协商最大报文段长度(MSS)时,或在高速网络环境下用作窗口调节因子时使用。首部字母中还定义了一个时间戳选项。
4. 6比特的标志字段。ACK比特用于指示确认字段中的值是有效的,即该报文段包括一个对已被成功接收报文段的确认。RST、SYN和FIN比特用于连接建立和拆除。
- 序号和确认号
- TCP报文段首部中两个最重要的字段是序号字段和确认好字段。这两个字段是TCP可靠传输服务的关键部分。
- 一个报文段的序号,是该报文段首字节的字节流编号,举例来说,假设主机A上的一个进程想通过一条TCP连接向主机B上的一个进程发送一个数据流。主机A中的TCP将隐式地对数据流中的每一个字节编号。假定数据流由一个包含500000字节的文件组成,其MSS为1000字节,数据流的首字节编号是0。该TCP将为该数据流构建500个报文段。给第一个报文段分配序号0,第二个报文段分配序号1000,第三个2000,以此类推。每一个序号被填入到相应TCP报文段首部的序号字段中。
- 确认号。TCP是全双工的,因此主机A在向主机B发送数据的同时,也许也接收来自主机B的数据(都是同一条TCP连接的一部分)。从主机B到达的每个报文段中都有一个序号用于从B流向A的数据。主机A填充进报文段的确认号是主机A期望从主机B收到的下一字节的序号。举个栗子,假设主机A已收到了来自主机B的编号为0~535的所有字节,同时假设它打算发送一个报文段给主机B。主机A等待主机B的数据流字节536及以后的所有字节。所以主机A就会在它发往主机B的报文段的确认号字段中填上536。
往返时间的估计与超时
TCP采用超时/重传机制来处理报文段的丢失问题。超时间隔必须大于该连接的往返时间,即从一个报文段发出到它被确认的时间。否则会造成不必要的重传。
可靠数据传输
因特网的网络层服务是不可靠的。IP不保证数据报的交付,不保证数据报的按序交付,也不保证数据报中数据的完整性。对于IP服务,数据报能够溢出路由器而永远不能到达目的地,数据报也可能是乱序到达,而且数据报中的比特可能损坏。由于运输层报文段是被IP数据报携带着在网络中传输的,所以运输层的报文段也会遇到这些问题。TCP在IP不可靠的尽力而为服务之上创建了一种可靠数据传输服务。
流量控制
一条TCP连接每一侧主机都为该连接设置了接收缓存。当该TCP连接接收到正确、按序的字节后,它就将数据放入接收缓存。相关联的应用进程会从该缓存中读取数据,但不必是数据刚一到达就立即读取。如果某应用程序读取数据时相对缓慢,而发送方发送得太多、太快,发送的数据就会容易使该连接缓存溢出。
TCP没它的应用程序提供了流量控制服务以消除发送方使接收方缓存溢出的可能性。
TCP发送方可能因为IP网络的拥塞而被遏制;这种形式的发送方的控制被称为拥塞控制。
流量控制:TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制。接收窗口用于给发送方一个指示-该接收方还有多少可用的缓存空间。
假设A向B发送一个大文件, 我们定义以下变量:
RcvBuffer为窗口大小
a:主机B上的应用进程才能够缓存读出的数据流的最后一个字节的编号
b:从网络中到达的并且已放入主机B接收缓存中的数据流的最后一个字节的编号。
那么b-a<=RcvBuffer才能避免缓存溢出
设rwnd=RcvBuffer-[b-a]
主机A轮流跟踪两个变量,LastByteSent和LastByteAcked,这两个变量的意义很明显。注意到这两个变量之间的差LastByteSent-LastByteAcked,就是主机A发送到连接中但未被确认的数据量。通过将未确认的数据量控制在值rwnd以内,就可以保证主机A不会使主机B的接收缓存溢出。