TCP全称是 Transmission Control Protocol,是传输控制协议。TCP在网络七层模型中的传输层。
我们程序的数据会首先进入TCP的segment中,然后TCP的segment会打到IP的package中,然后再到以太网的frame中,传到对端,各层解析自己的协议,然后把数据交由更高层的协议处理。
TCP头部格式
想要了解TCP,那就免不了需要熟悉TCP的头部
我们来分析一下TCP头部的几个字段的含义和作用
源端口/目的端口: 各占2个字节,表示数据从哪个进程来,去往哪个进程。
序号:占4个字节,TCP连接中传送的数据每一个字节都会上一个序号,序号字段的值就是本报文段发送的==数据的第一个字节的序号== 。
确认号:占4个字节,是期望收到对方下一个报文段的序号。
数据偏移:占4个字节,它指出TCP报文段的数据距离TCP报文段的起始处有多远(首部长度)。
- 紧急URG:当URG=1时,表明紧急指针字段有效。它告系统此报文段中有应急数据,应优先传送。
- 确认ACK:只有当ACK=1时,确认号才有效,否则无效。
- PSH:用来提示接收端应用程序立刻将数据从tcp缓冲区读走
- RST:当RST=1时,表明TCP连接中出现严重差错(如主机崩溃),需要释放连接并要求重新建立连接
- SYN:同步 SYN = 1 表示这是一个连接请求或连接接受的报文
- FIN:用来释放一个连接.FIN=1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接
校验和:占 2 字节.检验和字段检验的范围包括首部和数据这两部分.在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部
TCP 对比 UDP
- TCP 可以保证数据的正确性和可靠性,而 UDP 则允许数据丢失
- 除了增加了端口信息,UDP协议基本就没有对IP层的数据进行任何处理了,而TCP协议还加入了更加复杂的传输控制,比如滑动窗口,以及接收确认和重发机制,以达到数据的可靠传送。
- TCP协议提供了可靠传输,但是其拥塞控制、数据校验、重传机制的网络开销很大,不适合实时通信,所以经常选择开销很小的UDP协议进行通信。
- UDP 就像发短信,只管发出去,至于对方是不是空号(网络不可到达)能不能收到(丢包)等并不关心;TCP 就像打电话,双方要通话,首先,要确定对方是不是开机(网络可以到达),然后要确定是不是没有信号(网络可以到达),然后还需要对方接听(通信链接)。
TCP的三次握手
TCP 是面向连接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但 TCP 的三次握手在很大程度上保证了连接的可靠性。建立起一个 TCP 连接需要经过“三次握手”。
- 第一次握手:客户端发送 syn (Synchronization:同步) 包 (syn=j) 到服务器,并进入SYN_SEND 状态,等待服务器确认
- 第二次握手:服务器收到 syn 包,必须确认客户的 SYN (ack=j+1),同时自己也发送一个 SYN包(syn=k),即SYN+ACK (Acknowledge:承认)包,此时服务器进入SYN_RECV(Receive:接收)状态;
- 第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(Established:建立、确立) 状态,完成三次握手。
为什么要握手三次,而不是两次?
如果此时网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。
TCP四次挥手
第一次挥手:A已经发送完数据,请求释放连接,只发送报文头,此时A进入FIN_WAIT状态。
FIN=1,表示释放连接。
seq=u,u-1表示确认的最后一个数据序号。
第二次挥手:B收到连接释放请求之后,会告诉它A到B这个方向已经释放。B向A发送应答响应,B进入CLOSE_WAIT状态。
ACK=1:除TCP连接请求报文段以外,TCP通信过程中所有数据报的ACK都为1,表示应答。
seq= v:v-1是B向A发送的最后一个字节的序号。
ack=u+1表示希望收到从第u+1个字节开始的报文段,并且已经成功接收了前u个字节。第三次挥手:当B向A发完所有数据后,向A发送连接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。
B便进入LAST-ACK状态。第四次挥手:A收到释放请求后,向B发送确认应答,此时A进入TIME-WAIT状态。 该状态会持续2MSL时间,若该时间段内没有B的重发请求的话,就进入CLOSED状态,撤销TCB。当B收到确认应答后,也便进入CLOSED状态,撤销TCB。
为什么需要四次挥手
当关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。