概览
TCP是面向连接的
,基于字节流
的可靠
的全双工
的传输层
协议,可靠性通过拥塞控制
和超时重传
策略来保证。
- 面向连接
在真正通信之前,客户端和服务器之间要先建立一个连接。 - 可靠性(保障可靠的到达或通知)
tcp并不保证数据一定能传输到对端,这是不可能做到的。如果不能传输到,TCP放弃重出传并关闭连接,并通知应用层。
TCP含有用于动态估算客户端和服务器之间往返时间的RTT算法,以便知道等待下一个确认需要多久。 - 流量控制
TCP总是通过称为一个动态变化的通知窗口
的结构告知对端它一次可以接受多少个字节。在任何时候,该缓冲区告知对端当前可用空间量,从而确保发送端发送的数据不会超过使得接收缓冲区溢出。
TCP协议结构
TCP header源端口号
:端口指运行在主机上的应用进程,基于TCP协议传输数据的“发送方”。目的端口
:等待TCP协议发送方数据的“接收方”。序列号
:表示通信双方“单向”数据量流动数量表示,序列号记录的是以“字节”为单位的计数器(1字节=8比特)。例如A要传输给B的512字节数据,假设初始序列号为1024(注意:每次初始化序号都会不一样,TCP有一个比较复杂的初始化算法),那么他们传输过程的序列号为1536。序列号会随着双方“交流”而不断的增加,因为序列号一共32比特,所以最大值也就是2^32-1,到达最大值后重新从0开始。因为TCP是一个可靠的协议,序列号的存在是其可靠的关键因素之一。确认序列号
:确认序列号包含发送确认的一端所期望收到下一个序号。因此,确认序列号应当是上次已成功接收到数据字节序列号加1。只有ACK标识(下面会介绍)为1时确认序列号才生效。因为TCP为应用层提供双工服务,意味着数据能在两个方向上独立地进行传输,因此连接的每一端(客户端和服务端)必须保持每个方向上的传输序列号。例如A传送给B的序列号为1024(A维护),但B传送给A的有自己的序列号需要维护(B维护)。
首部长度
:TCP首部的“选项”不启用,那么TCP的头部就是20字节,但因为存在“选项”的部分,所以头部可能存在大于20字节的可能性。因为“首部长度标识”有4位,所以最大值为2^4-1=15,而这个标识维护头部的长度是以32比特为单元,所以头部最大长度为15*32比特(4字节)=60字节。
标志
:每个标志占1比特,1表示set
URG
:紧急指针(urgent pointer)有效;
ACK
:确认序号有效;
PSH
:接收方应该尽快将这个报文段交给应用层;
RST
:重建连接;
SYN
:同步序号用来发起一个连接;
FIN
:发送端完成发送任务;
窗口大小
:TCP的流量控制由连接的每一端通过声明的窗口大小来提供(以字节为单位),窗口大小是一个16比特字段,因而窗口最大为65535字节。
检验和
:检验和覆盖了整个的TCP报文段:TCP首部和TCP数据,用户保证传输的数据的可靠性(没有被篡改或丢失某些数据),由发送方计算和设置,并由接收方进行验证。
紧急指针
:只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个报文段。
选项
:就是TCP头部的不是“必须”的选项,例如常见的可选字段是“最长报文大小”,又称为MSS(Maximun Segment Size),每个连接方通常都在通信的第一个报文段中指明这个选项。
数据
:整个TCP报文段是又报文头部和报文数据组成的,除去了头部就是数据,但数据是可空的,例如创建连接(SYN)和结束传输(FIN)的TCP报文都是没有数据的。
TCP连接的建立和终止
连接-三次握手
三次握手
每个ACK是收到的SYN+1,表示期望收到的下一个SYN的值。
结束-四次挥手
四次挥手
通常结束TCP连接使用四个TCP segment,但是有时候终止segment的FIN可能随数据一起发送,步骤2和步骤3的两个确认都出自被动关闭侧,有可能被合并为一个分节。
TCP状态转换
TCP状态转换图- tcp为一个连接定义了11中状态,tcp规则规定如何基于当前状态以及当前状态所接受的分节从一个状态转化到另一个状态。
-
可以使用netstat工具查看tcp连接的状态
一个完整的TCP状态转化图
TIME_WAIT状态
- 执行主动关闭的一方,在收到对端的一个FIN的ACK确认之后,状态转变到TIME_WAIT。该状态停留的持续时长是2MSL(max segment lifetime)。MSL的时间一般在30s到两分钟之间,MSL表示任何一个ip数据包在网络中存活的最长时间。
- TIME_WAIT存在的理由
可靠的实现tcp全双工连接的终止
允许老的重复分节在网络中消逝
1)假设最后一个主动关闭方的ACK丢失了,被动结束方将重新发最终的那个FIN,主动结束方必须维护状态信息。要是主动结束方不维护状态信息,那么主动结束方将响应一个RST,该segment会被被动结束方识别为一个错误。
2)假设有一对套接字的ip分别为host1,host2,假设关闭连接后过段事件我们重新使用该连接,由于他们ip地址和端口都相同,tcp必须防止来自老连接网络中重复分组被新连接接收到。为此TCP将不给处于TIME_WAIT状态的连接在重新发起连接。由于TIME_WAIT的过期时间是2MSL,这足以让某个方向上的分组最多存活MSL后被丢弃,另一个方向上的应答最多也存活MSL秒。
tcp的输出
- 每个tcp套接字有一个发送缓冲区,当应用进程调用write向该socket写数据的时候,内核从该应用进程的缓冲区复制所有数据到写socket的发送缓冲区。如果该套接字的发送缓冲区容不下该进程的所有数据(或是应用进程的发送缓冲区大于socket的发送缓冲区,或是发送缓冲区已有其他数据),该应用进程将被投入睡眠。假设该socket是阻塞的,内核将不从write返回,知道应用进程的所有数据被拷贝到socket的内核发送缓区。因此从写一个套接字的write系统调用返回,仅代表应用进程的数据被全部拷贝到了内核的发送缓冲区,我们可以使用原来的应用进程缓冲区,并不代表对端TCP已经接收到数据。
- 对端TCP收到数据后,必须确认收到的数据,伴随对端ACK segment的到达,本段TCP才会认为数据已经发送到了对端,才会从发送缓冲区丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。
网友评论