TCP/IP协议三次握手、四次挥手
TCP/IP协议
TCP报文格式
)
TCP报文头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接
序号(4字节=32位):
用来标识TCP发送端向TCP接收端发送的数据字节流
确认序号(4字节=32位):
由于该报文为SYN报文,ACK标志为0,故没有确认序号(ACK标志为1时确认序号才有效)TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1一旦建立连接,该将始终发送(同ACK标志);
头部长度:该字段占用4位,用来表示报文首部的长度,单位4Byte。如:headLen = ((packet[12]>>4)&0x0F)*4;
预留6位:长度为6位,作为保留字段,暂时没有什么用处;
URG:长1位,表示紧急指针字段有效;
ACK:长1位,置位表示确认号字段有效;TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1;
PSH:长1位,表示当前报文需要请求推(push)操作;
RST:长1位,置位表示复位TCP连接;
SYN:长1位,在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1,因此,SYN置1就表示这是一个连接请求或连接接受报文;
FIN:长1位,用与释放TCP连接时标识发送方比特流结束;即完,终结的意思,用来释放一个连接。当FIN=1时,表明此报文的发送方的数据已经发送完毕,并要求释放连接;
窗口大小:长度位16位,2个字节;
校验和:长度位16位,2个字节;
紧急指针:长度16位,2哥字节;
以上是TCP包头必须要有的字段,也称固有字段,长度为20个字节;
TCP三次握手
TCP怎样才能保证可靠的传输任务,就是通过三次握手
首先由Client发出请求连接即SYN=1 ACK=0(请看头字段的介绍),TCP规定SYN=1时不能携带数据,但要消耗一个序号,因此声明自己的序号是seq=x 然后Server进行回复确认,即SYN=1 ACK=1 seq=y, ack=x+1, 再然后Client再进行一次确认,但不用SYN了,这时即为 ACK=1, seq=x+1, ack=y+1
TCP四次挥手
当客户端A没有东西要发送时就要释放A这边的连接,A会发送一个报文(没有数据),其中FIN设置为1,服务器B收到后会给应用程序一个信,这时A那边的连接已经关闭,即A不再发送信息(但仍可接收信息)。
A收到B的确认后进入等待状态,等待B请求释放连接,B数据发送完成后就向A请求连接释放,也是用FIN=1表示,并且用ack=u+1,A收到后回复一个确认信息,并进入TIME_WAIT状态,等待2MSL时间。
为什么要等待?为了这种情况:B向A发送FIN=1的释放连接请求,但这个报文丢失了,A没有接到不会发送确认信息,B超时会重传,这时A在WAIT_TIME还能够接收到这个请求,这时再回复一个确认就行了。另外服务器B存在一个保活状态,即如果A突然故障死机了,那B的连接资源什么时候能释放呢?就是保活时间到了后,B会发送探测信息,以决定是否释放连接。
注意:中断连接端可以是Client端,也可以是Server端
来个通俗版的解释:
假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!(是服务端先关闭,后客户端关闭)