TCP(传输控制协议)在两个端点之间提供可靠的、面向连接的、双向字节流通信信道。
确认、重传和超时
当一个TCP报文无错地到达目的地时,接受TCP会发送一个确认报文给发送端,该报文的确认序号字段被设置为接收方期望接收的下一个报文的逻辑序号。如果报文存在错误,那么这个报文会被丢弃,确认信息也不会被发送。发送方在发送报文后一段时间没有收到确认,就会重传报文。
流量控制(滑动窗口机制)
为了防止发送方发送速度过快而导致接收方来不及接收,在三次握手建立TCP连接的过程中就会告知对方接收缓冲区大小。从发送方接收数据到缓冲区时,空闲缓冲区大小减小;当上层应用从缓冲区读取数据时,空闲缓冲区大小增大。每次确认时,会告诉对方空闲缓冲区大小。如果缓冲区被填满,发送方暂停传输数据。
TCP连接的建立
在套接字API层,两个流式套接字通过以下步骤建立连接:
- 服务器调用listen()在套接字上执行被动打开,然后调用accept()阻塞服务器进程直到连接建立完成。
- 客户端调用connect()在套接字上执行主动打开,以此来同服务器端的被动打开套接字之间建立连接。
三次握手
建立一个TCP连接,需要传送3个报文,步骤如下:
- connect()调用导致客户端TCP节点发送一个SYN报文到服务器端TCP节点,告知服务器客户端TCP节点的序列号(SYN=1,seq=x)。
- 服务器TCP节点收到客户端发来的TCP报文后,返回一个设置SYN和ACK控制位的报文(SYN=1,ACK=x+1,seq=y)
- 客户端TCP节点发送一个ACK报文来确认服务器端TCP节点的SYN报文(ACK=y+1)
TCP连接的终止
关闭一个TCP连接的过程:
- TCP连接的一段执行close()系统调用,主动关闭TCP连接
- 稍后另一端也执行一个close()系统调用被动关闭
四次挥手
假设由客户端发起主动关闭,TCP连接的终止过程需要传送四个报文:
- 客户端TCP节点发送一个FIN报文给服务器(FIN=1,seq=x)
- 服务器端TCP节点接收到FIN报文后,发出ACK报文作为响应。之后,服务器端的read()都会返回0(ACK=x+1)
- 当服务器端完成数据传输时,服务器端TCP节点发送FIN报文到客户端(FIN=1,seq=y)
- 客户端TCP节点发送ACK报文并进入TIME_WAIT状态,如果服务器端没有收到客户端传来的ACK报文,则可以重传FIN报文。客户端等待2个MSL(最大报文段生存时间)
TIME_WAIT状态的作用
- 确保能可靠地终止连接,如果执行主动关闭的一方发出的最后一个ACK报文丢失,那么执行TCP被动关闭的一方会重传FIN报文。让执行主动关闭的一方在TIME_WAIT状态保持2个最大报文生存时间,可以确保收到执行被动关闭的一方重传的FIN报文,并发送ACK确认报文。如果执行主动关闭的一方已经不存在了,那么TCP协议将针对重发的FIN发送一个RST(重置)给执行被动关闭的一方,这个RST会被解释成一个错误。
- 确保老的重复报文在网络中过期失效TCP节点处于TIEM_WAIT状态时无法通过该节点创建新的连接。TCP重传的报文有可能在连接终止后才到达。假设通信双方使用相同的IP和端口重新建立TCP连接,如果没有TIME_WAIT状态使老的报文失效,这新老的报文有可能被当做新的合法报文。
参考资料
《Linux编程手册(下)》
计算机网络之面试常考
在浏览器中输入 google.com 并且按下回车之后发生了什么?
What is the difference between UDP and TCP internet protocols?