TCP
协议相对于UDP
协议的特点
一、 有连接
使用TCP
协议通信的双方必须先建立连接,然后才能开始数据的读写。双方必须为该连接分配必要的内核资源,以管理链接的状态和和连接上数据的传输。完成数据交换之后,双方都必须断开连接以释放系统资源。
一般而言,TCP
连接是由客户端发起,并通过三次握手建立连接。
TCP
连接的关闭过程相对复杂一些。可能是由客户端主动执行关闭,也可能服务器端因为某些原因,比如服务器程序被中断而强制关闭连接。
二、 面向字节流
面向字节流和面向数据报的区别在于通信双方是否执行相同次数的读、写操作。发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系。应用程序对数据的发送和接收是没有边界限制的。
当发送端应用程序连续执行多次写操作时,TCP
模块先将这些数据放到TCP
的发送缓冲区。当TCP
模块真正开始发送数据时,发送缓冲区中这些等待发送的数据可能被封装为一个或多个TCP
报文段发出。
当接收端收到一个或多个TCP
报文段后,TCP
模块将他们携带的应用程序数据按照TCP
报文段的序号依次放入TCP
接收缓冲区,并通知应用程序读取数据。接收端应用程序可以一次性将TCP
接收缓冲区中的数据全部读出,也可以分多次读取,这取决于用户指定的应用程序读缓冲区的大小。
而UDP
协议,发送端每执行一次写操作,UDP
模块就将其封装为一个UDP
数据报并发送之。接收端必须及时针对每一个UDP
数据报执行读操作,否则就会丢包。如果用户没有指定足够的应用程序缓冲区来读取UDP
数据,则UDP
数据将被截断。
三、可靠传输
1. 发送应答机制
发送端发送的每个TCP
报文段都必须得到对方的应答,才认为TCP
报文段传输成功。
2. 超时重传机制
发送端在发送出一个TCP
报文段之后启动定时器,如果在定时时间内未收到应答,它将重传该报文段。
3. 有序到达
TCP
报文段最终是以IP
数据报发送的,而IP
数据报到达接收端可能乱序,重复,所以TCP
协议还会对接收到的TCP
报文段重拍整理,再交付给应用层。
四、TCP头部结构
16位端口号(port number):告知主机该报文段是来自哪里(源端口)以及传输给哪个上层协议或应用程序(目的端口)。
32序号(sequence number): 一次TCP
通信过程中某一个传输方向上的字节流的编号。
32位确认序号(acknowledgement number): 用作对另一方发送来的TCP
报文段的响应。其值是收到的TCP
报文段的序号值加1。
4位首部长度(header length): 标识TCP
头部有多少个4字节。TCP
头部最长60字节。
6位标志位:
- URG标志,表示紧急指针(urgent pointer)是否有效
- ACK标志,表示确认序号是否有效。---- 确认报文段
- PSH标志,提示接收端应用程序应该立即从
TCP
接收缓冲区中读走数据,为接收后续数据腾出空间。 - RST标志,表示要求对方重新建立连接。---- 服务报文段
- SYN标志,表示请求建立连接。 ---- 同步报文段
- FIN标志,表示通知对方本段要关闭连接了。---- 结束报文段
16位窗口大小(window size): 是TCP
流量控制的一个手段,它告诉对方本段TCP
接收缓冲区还能容纳多少字节的数据。
16位校验和(TCP checksum): 由发送端填充,接收端对TCP
报文段(整个TCP报文)执行CRC
算法以检验TCP
报文段在传输过程中是否损坏。
16位紧急指针(urgent pointer): 它是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。----紧急偏移
五、TCP的连接超时
在TCP
三次握手建立连接的过程中,如果客户端访问一个距离它很远的服务器或者由于网络繁忙,导致服务器对于客户端发送出的同步报文段没有应答,此时客户端将执行多次重连操作,TCP
模块一共执行6次重连操作,每次重连的超时时间加倍(1s、2s、4s、8s、16s、32s)。在6次重连均失败的情况下,TCP
模块放弃连接并通知应用程序。
关于tcp
重连次数可以查看文件/proc/sys/net/ipv4/tcp_syn_retries
六、TCP状态转移
服务器通过listen
系统调用进入LISTEN
状态,被动等待客户端连接;当服务器监听到某个连接请求(收到同步报文段),就将该连接放到内核等待队列中,并向客户端发送带SYN
标志的确认报文段,此时该连接处于SYN_RCVD
状态。如果服务器成功的接收到客户端发送回的确认报文段,则该连接转移到ESTABLISHED
状态;ESATBLISHED
状态是连接双方能够进行双向数据传输的状态。
当客户端主动关闭连接时(通过close
或shutdown
系统调用向服务器发送结束报文段),服务器通过返回确认报文段使连接进入CLOSE_WAIT
状态。这个状态的含义很明确:等待服务器端应用程序关闭连接。通常,服务器检测到客户端关闭连接后,也会立即给客户端发送一个结束报文段来关闭连接。这将使连接转移到LAST_ACK
状态,以等待客户端对结束报文段的最后一次确认。一旦确认完成,就彻底关闭连接。
客户端通过connect
系统调用主动与服务器端建立连接。connect
系统调用首先给服务器端发送一个同步报文段,是连接转移到SYN_SENT
状态。此后,connect
将会因为以下两个原因返回:
- 如果
connect
连接的目标端口不存在(未被任何进程监听),或者该端口仍被TIME_WAIT
状态的连接占用,则服务器端将给客户端发送一个复位报文段,connect
调用失败。 - 如果目标端口存在,但
connect
在超时时间内未收到服务器的确认报文段,则connect
调用失败。
connect
调用失败将使连接立即返回初始的CLOSED
状态。如果客户端成功的收到服务器端的同步报文段和确认,则connect
调用成功返回,连接转移至ESTABLISHED
状态。
当客户端执行主动关闭时,它将向服务器发送一个结束报文段,同时连接进入FIN_WAIT_1
状态。若此时客户端收到服务器专门用于确认的确认报文段,则连接转移到FIN_WAIT_2
状态。此时,如果服务器端也关闭连接(发送结束报文段),则客户端将给予确认并进入TIME_WAIT
状态。