Internet传输协议:TCP

时间:2021-12-03 10:17:43

传输控制协议(TCP,transmission control protocol)设计它的目的是为了在互联网上提供一种可靠的端到端的字节流。

TCP段的头

下面的这张图是TCP段的结构,由三部分组成,一是固定长度的头,共20个字节;二是可选字段;三是数据字段,数据字段也可以为空,这类TCP段通常被用作确认和控制信息。
Internet传输协议:TCP
下面我们看一下各个字段的含义;
源端口(source port)和目的端口(destination port),顾名思义就是指发送方和接收方的端口。
序号(sequence number)和确认号(ackonwledgement number),TCP中的每一个字节都有其都有的序号,确认号指的是下一个期待的字节,而不是已经接收到的最后一个字节。
TCP头长度(TCP header length)指明了TCP头中包含了多少个32位(4字节)的字。由于可选部分是可变长的,所以必需明确地指出头的长度。
和IP头类似,TCP头也有一些保留位,原先是6位,不过现在有两位被重新声明使用了。分别是CWR和ECE,他们都是用作拥塞控制信号的。当接收方收到网络拥塞的信号时,就设置ECE,给发送端发ECN-Echo信号,告诉发送端放慢发送的速度;发送端收到这个信号后,会设置CWR给接收端,告诉接收端我已经放慢了速度,你不用再给我发ECN-Echo信号了。
URG(urgent pointer),表示是否使用紧急指针。
ACK表示确认号是否有效,ACK为1表示有效。
PSH表示这是被推送的数据,接收端一旦接收到数据后马上交给应用程序,而不是等缓冲区满了在提交。
RST被用于突然重置一个已经变得混乱的连接,如果这个字段被标识了说明你遇到问题了。
SYN用于建立连接过程。它和ACK配合使用,在连接请求中SYN=1,ACK=0表示该段没用使用捎带确认字段。但是连接应答捎带一个确认信息SYN=1,ACK=1。本质上SYN即表示connection request又表示connection accepted,然后用ACK进一步区分。
FIN用于释放一个连接,表示发送端已经把数据发送完了。
窗口大小(Window size),TCP中的流量控制是通过一个可变大小的滑动窗口来处理的,窗口大小字段从被确认的字节算起还可以发送多少个字节。窗口大小可以为0,表示希望别再发送数据了。
校验和(checksum),它是对TCP头和数据的校验。
选项(options),提供了一种添加额外设施的途径,主要针对常规头覆盖不到的方面。最长可以扩展到40字节。用途最广的选项允许每台主机制定他愿意接受的最大段长,大段比小段效率高,默认是536字节的有效载荷。

TCP三次握手

建立一个连接似乎很简单,发送方给接收方发一个connection request然后等待接收方给自己回复一个connection accept就可以了。但是事实却很复杂,让我们考虑一下这种情况:用户建立一个与银行的连接,告诉银行把一大笔钱转给另一个人,不过这个数据包走的那条路由路径遇到了拥塞,然后,发送端超时,所以用户再次发送这个消息,这次数据包顺利的到达了,所以发送端释放链。可是,问题出现了,原来那个被堵塞数据包现在也到达了,要求银行建立一个新的连接和汇款。银行没法得知这些是重复的请求,于是就把它当做一个新的请求,再次进行转账。这就是延迟重复问题。为了解决这个问题人们提出了几种方案;
1、为每一个连接分配一个唯一的标识符,就是一个序号,每建立一个连接序号就递增,把这个标识符放入段中,包括请求建立连接的那个段,这样一来,每个传输实体就可以知道所有已经过期的连接。不过这种方法有一个巨大的缺陷,就是每个传输实体必须维护一张巨大的表,用来存放那些过期的序号。这样做的代价太大了。
2、第二种方法就是我们不允许数据包在网络中无限期的存活,可以设计一种机制来杀死那些在网络中停留时间过长的数据包。主要有两种方式:一、为每个数据包添加一个跳计数器;二、为每个数据包打时间戳。为了确保这个数据包确实死了,我们引入周期T,它是数据包最大生存周期的某个不太大的倍数(120秒的倍数),也就是说数据包发送出去T秒后,我们就可以确信这个数据包就彻底死了。
这样一来我们就有一种万无一失的方法来解决延迟重复问题了,其核心就是:源端用序号作为段的标识,使得该段在T秒内不得重复使用,也就是说序号空间足够大,当序号循环使用了一遍时,已经过了T秒。
三次握手过程:1、主机1发送序号为x的连接请求给主机2;2、主机2收到请求后,回应一个ACK段作为对x的确认,并且宣告它自己的序号y,最后,主机1在他发送的第一个数据段中,对主机2选择的初始序号进行确认。如下图;
Internet传输协议:TCP