一、TCP特性
TCP协议是TCP/IP协议族中另一个重要的协议。与IP协议相比,更接近于应用层。
传输层协议主要有两个:TCP协议和UDP协议
相较于UDP,TCP协议的特点是:面向连接、字节流、可靠传输
过程:
1.双方首先进行,需要为连接分配必要的内核资源,管理连接状态和数据传输
2.双方读写都是通过同一个连接进行的
3.完成数据交换后,通信双方应该断开连接以释放系统资源
TCP:
UDP:
需要注意:
- TCP协议用于1对1,即不能用于基于广播和多播的应用程序
- TCP连接双方的收发数据次数不一定相同,即发送多次的数据包,可能会被对方1次全部接收
- TCP在发送数据报后,必须得到接收方的应答,才认为传输成功,所以是可靠的
- TCP采用超时重传机制,超过时间没收到应答,就会重新发送。
二、TCP头部结构
TCP头部信息在每个TCP报文段中,用于指定通信双方地址
连接状态等
- 16位端口号:指定数据从哪个端口来,发送到哪个端口。
- 32位序号:一次TCP通信中,每段字节流的编号。如A与B通信,第一个报文中,序列值被系统初始化为随机值,之后的传输(A到B),该序号值将被设定为初始值加上第一个字节在整个字节流中的偏移。
- 32位确认号:用作对另一方发送的TCP报文段的响应,其值是收到的TCP报文段序号值加一。
- 4位头部长度:标识该TCP头部有多少个32bit字(4字节),即最长为60字节
- 6位标志位:
- URG:标识紧急指针是否有效
- ACK:标识确认号是否有效
- PSH:提示接收端应立即从TCP接收缓存区中读走数据
- RST:表示要求对方重新建立连接
- SYN:表示请求建立一个连接
- FIN:通知对方关闭连接 - 16位窗口大小:TCP流量控制的一个手段,告诉对方本地TCP接收缓存区还能容纳多少字节的数据
- 16位校验和:由发送端填充,接收端对TCP报文段执行CRC算法校验数据是否损坏。
- 16位紧急指针:正的偏移量,它和序号字段的值相加表示最后一个紧急数据的下一个字节序号
- 选项:为可变长的可选信息
典型选项结构:
- kind:说明选项的类型
- length:选项的总长度
- info:选项的具体信息
常见TCP的7种选项:
kind=0:选项表结束
kind=1:空操作,一般用于将TCP选项的总长度填充为4字节的整数倍
kind=2:最大报文段长度选项,初次连接,双方通过此选项协商最大报文长度,TCP通常设置此为MTU-40字节,避免被分片
kind=3:窗口扩大因子选项。TCP头部通知窗口为N,扩大因子为M,则实际接收通知窗口为N*(2的M次方),且只能出现在同步报文段中,否则被忽略
kind=4:选择性确定(Selective Acknowledge,SACK)。如果某个TCP报文段丢失,则TCP模块会重传最后被确认的TCP报文段后续所有报文段。而该选项则可解决这种问题。
kind=5:SACK实际工作选项。告诉发送端本端已经收到的数据块,从而让发送端只发送丢失的数据
kind=8:时间戳。提供通信双方较为精确的回路时间。
二、TCP连接的建立与关闭
建立过程:
第一个TCP报文段:包含SYN标志,表示它是同步报文段,即向服务器发送连接请求,同时包含一个535734930的序号
第二个TCP报文段:包含SYN,也是同步报文段,表示服务器同意建立连接。同时给客户端发送535734931序号,表示确认收到上一条消息,并发送自己的序号2159701207.
第三个TCP报文段:回应序号为2159701208的报文段,表示确认收到上一条服务器的消息。
至此,TCP连接成功建立,该过程被称为TCP三次握手
关闭过程:
第四个报文段:包含FIN标志,为结束报文段,即通知服务器自己要断开连接,并发送序号。
第五个报文段:服务器确认该结束报文段
第六个报文段:服务器发送自己的结束报文段
第七个报文段:客户端确认服务器的结束报文段
至此连接断开,该过程被称为4次挥手
三、半关闭状态
由于TCP连接允许两个方向的数据传输被独立关闭,所以当其中一方发送结束报文给对方,并收到其确认报文,会等待对方发送结束报文,这就成为半关闭状态
当处于半关闭状态时,依然能继续接收对方的消息,直至对方发送结束报文
而判断对方是否关闭连接的方法就是,read方法返回0
四、连接超时
当一个客户端访问一个距离它很远的服务器或者网络繁忙时,就可能导致服务器对客户端发送的报文没有应答。
此时客户端程序就必须先进行重连,可能会执行多次,如果重连依旧无效,则会通知应用程序连接超时。
五、TCP状态转移
完整TCP状态转移图如下:
对于服务器来说:
通过listen函数调用进入LISTEN(监听)状态,被动等待客户端连接,因此执行的被动打开
一旦监听到某个连接请求,就将该连接放入内核等待队列中,并向客户端发送带有SYN标志的确定报文,此时该连接处于SYN_RCVD状态。
如果服务器成功接收到客户端发回的确认报文,则该连接转入到ESTABLEISHED状态,此时连接双方就能够进行双向数据传输。
当客户端主动关闭连接时,服务器通过返回确认报文使连接进入CLOSE_WAIT状态:等待服务器应用关闭连接,而通过服务器检测到客户端关闭后也会立即给客户端发送一个结束报文,使得连接转入LAST_ACK状态,以等待客户端的确认,一旦接收到客户端的确认报文,连接就彻底关闭了
对于客户端来说:
通过调用connect函数主动向服务器发送连接请求,使连接转移到SYN_SENT状态。
如果连接目标端口没有被服务器监听,或者被其它占用,则服务器将向客户端发送一个复位报文段,连接失败。
如果在超时时间内没有收到服务器的确认报文,则连接也失败。
当连接失败,连接将立即返回初始的CLOSED状态,如果连接成功,则连接转移到ESTABLESHED状态,可以进行通信。
当客户端主动执行关闭时,将向服务器发送一个结束报文,连接进入FIN_WAIT_1状态。
如果此时客户端接收到服务器的确认报文,则连接转入FIN_WAIT_2状态,此时服务器处于CLOSE_WAIT状态,当前状态就处于半关闭状态。
当服务器发送结束报文后,客户端将回应确认报文,并进入TIME_WAIT状态。
当客户端来到TIME_WAIT状态时,客户端连接要等待长为2MSL的时间才能完全关闭,MSL时TCP报文段在网络中最大生存时间,标准建议为2min。
该特性保证可靠的终止TCP连接,让迟来的TCP报文段有足够的时间被识别并丢弃。
复位报文段
在某些特殊情况下,TCP连接的一端会向另一端发送携带RST标志的报文段,即复位报文段。
如:
当访问不存在的端口,异常终止连接和处理半打开连接时
TCP交互数据流与成块数据流
TCP报文段根据所携带的应用数据长度可分为两种:交互数据和成块数据。
交互数据仅包含很少的字节,这种应用程序对实时性要求很高,如telent、ssh等
成块数据通常长度通常为TCP报文段允许的最大数据长度,这种应用程序对传输效率要求高,如ftp
带外数据
有些传输协议具有带外数据的概念,用于迅速告知对方本端发生的重要的事情,因此带外数据比普通数据有更高的优先级。
UDP没有实现带外数据,TCP也没有正真的带外数据,但可以利用头部中的紧急指针标志和紧急指针两个字段给应用程序提供了一种紧急方式,
TCP超时重传
TCP模块为每个TCP报文段都维护了一个重传定时器,该定时器在TCP报文第一次被发送时启动。
如果超时时间内没有收到对方的应答,TCP模块将重传TCP报文段,并重置定时器。
而下一次重传的超时时间如何选择以及最多执行多少次重传就取决于TCP的重传策略了