TCP传输控制协议是一个面向连接的协议,在运行此协议进行数据传输前要进行连接的建立(三次握手),当数据传输完成,要进行连接释放(四次挥手)。
TCP的六个标志位:
URG:紧急指针标志位,URG=1时表明紧急指针字段有效。
ACK:确认标志位,ACK=1时,确认号字段才有效,连接建立后ACK必须置1。
PSH:推送标志位,尽快交付应用进程,不用等缓存区满。
RST:复位标志位,RST=1时,释放TCP连接然后重新建立连接。
SYN:同步标志位,在建立连接时用来同步信号,当SYN=1,ACK=0时,是请求连接报文段。SYN=1,ACK=1时,是同意建立连接。
FIN:终止标志位,FIN=1时,表明此报文段发送方数据已发送完,请求释放连接。
在三次握手和四次挥手中主要用到了SYN、ACK和FIN标志位。
传输控制块TCB:存储连接的重要信息,包括TCP连接表到收发缓存的指针、重传队列指针、发送和接受序号等。
三次握手:
假设有A、B两台主机,发起请求的主机认为是客户端,另一台认为是服务器。(所以认为服务器不是固定的)
第一次:客户端A主动打开连接,服务器B被动打开连接,B的服务器进程先创建传输控制块TCB,准备接受客户连接请求,A的客户进程也首先创建传输控制块TCB,并向B发送连接请求,A向服务器B发送SYN=1的标志位,并随机生成一个初始序号seq=x,(该报文不携带数据,但仍然需要消耗一个序列号)。当服务器B收到报文后,通过SYN=1,服务器B认为客户A想建立连接。
第二次:服务器B同意后向客户A发送确认,确认报文ACK=1,SYN=1,确认序号ack=x+1,并随机生成服务器初始序列seq=y。(该报文不携带数据,但仍然需要消耗一个序列号)。
第三次:A收到报文段后,检测ACK是否为1,和确认序列号是否为x+1。然后再向B发送最终确认,报文ACK=1,自己的序号:seq=x+1,确认号:ack=y+1。(该报文段可以携带数据,若不携带则不消耗序列号,下个报文段序列仍为x+1)。至此三次握手完成。
问:为什么必须是三次握手,而不能是两次?
答:为了防止已失效的(在网络滞留,超时重传)A连接请求又传至服务器B,若A此时已断开连接,则B会认为是新的请求,则响应,若不需要第三次A确认,则连接建成,但A并不认为建立成连接。则造成B资源浪费。
四次挥手:
第一次:当数据传输结束,客户A主动关闭TCP连接,但需要告诉B连接释放请求。发送报文段FIN=1,seq=u。(FIN报文段即使不携带数据,也要消耗一个序列号)可理解我A向B说我的数据已发送完,我准备断开连接。
第二次:B收到A的连接释放报文段后,由于TCP是双向全双工的双向连接协议,服务器B不会直接发送FIN=1的确认释放连接报文,而是先发送ACK=1的确认收到连接释放请求的报文段。可以理解为B对A说,我已收到你的请求关闭消息,但我还没有发送完数据,你再等我一下。
第三次:当B将数据传输完,B向A发送一个FIN=1,ACK=1的请求关闭连接报文。然后B被动关闭连接,但仍需等A最终的确认报文。
第四次:A收到FIN=1的报文后,向B发送ACK=1的确认报文。注意此时TCP连接还没有释放,A进入TIME-WAIT状态(进入该状态是为了防止网络不稳定引发的问题和B没有收到最终确认报文)。A等待2MSL时间后没有收到B的重传报文,连接才真正释放 。
问:为什么要四次挥手而不是三次?
答:若将第二次和第三次挥手合并,会造成B还没法送的数据发送不出去的问题;若没有第四次挥手,则有可能在网络上拥塞的数据接收不到等问题。