1)tcp报文格式
序号(Sequence number):seq序号是数据包本身的序列号,即告诉接收端要发送的数据包序列号。
确认号(Acknowledge number):ack序号是期望对方继续发送的那个数据包的序列号。
标志位:
(1)URG(urgent紧急):紧急指针(urgent pointer)有效。
(2)ACK(acknowledgement 确认):确认序号有效。
(3)PSH(push传送):接收方应该尽快将这个报文交给应用层。
(4)RST(reset重置):重置连接。
(5)SYN(synchronous建立联机):发起一个新连接(在建立TCP连接的时候使用)
(6)FIN(finish结束):释放一个连接,表示没有数据需要发送了(在关闭TCP连接的时候使用)
2)三次握手(建立TCP连接)
第一次(A—>B),SYN=1,seq=x
(1st)A将标志位SYN置为1,产生一个值x作为自己的seq序号,并将该数据包发送给B,A进入SYN_SENT状态(在发送连接请求后等待匹配的连接请求),等待B确认。
第二次(B—>A),SYN=1,ACK=1,seq=y,ack=x+1
(2nd)B收到数据包后根据标志位SYN=1知道A请求建立连接,B将标志位SYN和ACK都置为1,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y,并将该数据包发送给A以确认连接请求,B进入SYN_RCVD状态(在收到和发送一个连接请求后等待对连接请求的确认)。
第三次(A—>B),ACK=1,seq=x+1,ack=y+1
(3rd)A告诉B收到了B的确认消息并准备建立连接,A自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包。A和B进入ESTABLISHED状态(代表一个打开的连接,数据可以传送给用户),完成三次握手,随后A与B之间可以开始传输数据。
补充:TCP的三次握手最主要是防止已过期的连接再次传到被连接的主机。
假设一种异常情况,A发出第一个连接请求,这个请求在某些网络结点滞留,于是A在重新发送请求,后来收到了确认,建立了连接,数据传输完毕后,就释放了连接。这时B又收到了那个过期的连接请求,如果不采用三次握手,AB就又建立了连接,而这个连接是过期的。
3)四次挥手(释放TCP连接)
(1)A先向它的TCP发出连接释放报文,停止发送数据,主动关闭TCP连接,A将FIN置1,seq=u(前面传送的最后一个数据序号+1),这时A进入FIN_WAIT_1状态(四次挥手开始,主动关闭,发送断开连接请求,等待对端确认)等待B的确认。
(2)B收到连接释放请求发出确认,确认号ack=u+1,此报文的序号为v(B前面传过得数据序号+1)seq=v,然后B 进入CLOSE_WAIT状态(被动关闭,确认连接终止请求,但是未向对端发送连接终止请求(可能数据没传完))。
(3)A收到来自B的确认后,就进入FIN_WAIT_2状态(接收对方确认,但未接受对方的断开连接请求),如果B没有数据要发送,就通知TCP释放连接。这时B将FIN置1,假定此时B的序号为w(B可能还发送了一些数据),seq=w,ack=u+1(重复上次已发送的确认号),这时B进入LAST_ACK状态(数据传完,向对端发起断开连接请求后等待确认)。
(4)A收到B的连接释放报文段,对此发出确认,在确认报文段中将ACK置1,ack=w+1,seq=u+1,然后进入TIME_WAIT状态(表示收到对方的FIN报文并发送了ACK报文,就等2MSL后即可回到CLOSED状态了)。
补充:a)为什么握手只要三次,挥手要四次:在TCP三次握手中,服务器端的SYN和ACK是放在同一个TCP报文段中向客户端发送的,而在断开连接的过程中,服务器端向客户端发送的ACK和FIN是分别在两个不同的TCP报文段中。这是因为在服务器端接收到客户端的FIN后,服务器端可能还有数据要传输,所以先发送ACK,服务器端把数据发完之后就可以发送FIN断开连接了。
b)为什么要等2MLS后才能回到CLOSED状态:这个TIME_WAIT 状态的作用就是用来重发可能丢失的ACK报文。