tcp报文段首部
- 最前面两个分别是源端口和目的端口,各占2个字节
-
Sequence Number是包的序号,用来解决网络包乱序(reordering)问题(seq是初始化序号的简称)。
- 比如:一段报文,seq为301,携带100字节的数据,表明第一个字节的序号是301,最后的字节序号是400,期望下一个报文段的数据序号从401开始,则服务器或客户端发的下一个报文段的序号字段应为401.
-
Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题。(此为确认号,并非tcp flag的ACK)
- 期望收到对方下一个报文段的第一个数据字节序号。如若ACKnum = N,则表明到N-1为止的所有数据都已经正确收到。
- TCP Flag ,也就是包的类型,主要是用于操控TCP的状态机的。
- URG:当TCP Flag中的URG为1时,则表明紧急指针字段有效,告诉操作系统,报文段中有紧急数据、
- ACK:仅当ACK =1时,确认号才有效。当ACK = 0时,确认号是无效的。TCP规定,在连接建立后所有传送的报文段都必须把ACK设为1。(有效的确认连接已经建立)
- PUSH(推送):当这个设置为1时,接收方会尽快的将收到的报文段交付给接受应用进程,而不等到缓存满了再交付
- RST(复位):当收到的报文段rst为1时,表明tcp连接中出现严重的差错,必须释放连接,然后再重新建立连接,还用来拒绝一个非法报文段和拒绝打开一个连接。
- SYN(同步):在连接建立时用来同步序号。当SYN =1而ACK =0时,表明这是一个请求连接报文段。对方若同意建立连接,则应当在响应报文段中使用SYN=1 和ACK =1。
- FIN(终止): 用来释放一个连接,当FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。
- Window又叫Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的
- 窗口指的是发送本报文段的一方的接受窗口。窗口值告诉对方:本报文段首部的确认好算起,接收方目前允许对方发送的数据量。窗口值作为接收方让发送方设置其发送窗口的依据
- 比如,确认号是701,窗口字段是1000,这就表明,从701�号算起,发送此报文段的一方还有接受1000个字节数据(字节序号是701~1700)的接受缓存空间。
tcp三次握手
- TCP是面向连接的协议,为什么要三次握手呢?
- 要使每一方能够确知对方的存在
- 避免了服务器资源的浪费,预防连接请求延迟到达时,服务器依旧打开连接等待客户端。
- 默认情况下,client(客户端)为主动打开连接,server(服务端)为被动打开连接。
- 1.一般服务器进程会先创建传输控制块TCB,准备接受客户端的连接请求,然后服务器进程就处于listen(监听)状态,等待连接请求。
- 2.client进程在发起连接之前也会创建一个TCB,然后向server发出连接请求报文段,这时候首部的
同步位SYN =1
,同时会选择一个初始化序号seq = x
。tcp规定,SYN报文段不能携带数据,但要消耗一个序号,这时候发送完SYN报文后,client进入SYN-SENT(同步已发送)
状态. - 3.server收到请求报文段后(SYN报文),如同意建立连接,则向client发送确认报文段,在确认报文段首部把
SYN位和ACK位都设置为1.
,然后AckNum确认号 为x+1
,同时也为自己选择一个初始化序号seq = y
。
在此报文段中依然不能携带数据,但同样要消耗掉一个序号,此时server进入SYN-RCVD(同步收到)
状态 - 4.此时client收到server的确认后,还要给server发送确认,此时是第三次握手。发送的确认报文段
ACK置1
,确认号AckNum为 ack= y+1.
而自己的序号seq = x+1
,这时候,tcp规定可以携带数据,但不携带数据则不消耗序号
。这说明,下一个数据报文段的seq仍是 x+1
.这时候。tcp连接已经建立,client也进入ESTABLISHED(已建立连接状态
). - 5.当server收到client的确认后,也进入了
ESTABLISHED状态
- 三次握手主要是为了防止已失效的连接请求报文突然又传送到server,因而产生错误,从而浪费server的资源。有了第三次的话,client不发送第三次确认server的确认,server由于收不到第三次确认,就是的client并没有需要建立连接。
四次握手,释放连接
1.同理三次握手,client先发送一个连接释放报文段给server,
并停止发送数据
,主动关闭tcp连接,这个报文段的首部将tcp flag中的FIN为设置为1
,然后将seq = u
,等于把前面已传送过去的数据最后一个字节+1.此时client由ESTABLISHED状态进入FIN-WAIT-1(终止等待1)状态
。等待server的确认,请注意,FIN报文段即使不携带数据
,也会消耗一个序号。2.当server收到FIN报文后,会立即发出
确认ack=1,ACKnum =u +1,然后自己的序号为v
,发出去后则进入CLOSE-WAIT(关闭等待)状态
.这个时候server会通知高层应用进程,这时TCP连接进入半关闭(half-close)状态,就是client已经没有数据发给server,而server如果还有数据发给client,client仍要接收,这个状态还持续一段时间。3.当client收到server的确认后,就进入了
FIN-WAIT-2(终止等待2)状态
,等待server发出关闭连接报文。4.当server已经没有更多数据要向client发送的时候,就会发出server的FIN报文段,然后必须重复发送上次的
确认号AckNum为 ack= u+1
,在设置自己的序号seq=w
此时server就会进入LAST-ACK(最后确认)状态
,等待client的确认。5.当client受到server的连接释放报文后,必须对此发出确认。在确认报文段把
ack置1
,确认号AckNum为 ack= w+1
。而自己的序号为 seq = u+1
。然后则进入 TIME-WAIT。此时TCP连接还没释放
,必须等待2MSL(2次最长报文段寿命:2*2分钟)
.等待完后才进入CLOSED状态,而server收到最后ACK的时候就会进入CLOSED,比client早一点。-
为什么需要等待2MSL时间呢?
- 1.为了保证client发送的最后一个ACK报文段能够到达server,假如,这个最后ACK报文段丢失了,则server就处在LAST-ACK状态中,一直收不到自己刚刚发给client的FIN+ACK的报文段的确认报文。server就会再次重传一次FIN+ACK。而client就能在2MSL时间内收到重传的FIN+ACK报文,从而client在最后TIME-WAIT的状态中可以再次重传一次对server的FIN+ACK报文的确认报文。重启2MSL计时器。
- 这样如果client不在TIME-WAIT等待一段时间,而是在发送第一次ACK报文后立即释放连接,如果这个ACK报文丢失后,就无法收到server重传的FIN+ACK报文,因而不会再次发送ACK报文段,server就无法正常进入CLOSED状态。
- 2.还有一个原因是为了防止已经失效的报文段在新的连接中出现。因为client发送完最后一个ACK报文段后,等待2MSL后,会使本次连接内所有产生的报文段在网络中小时。
总结
- 无论三次握手与四次握手,双方的序号seq与acknum都要保持同步,比如server发送seq =x,client则会发送acknum=x+1.
- 每次握手都需要确认上一次握手,tcp flag中的标志位是发起连接或者释放连接的关键。