TCP 作为互联网核心协议之一,全名Transmission Control Protocol
首先了解一些基础概念:
一些基础概念
六个控制位
-
SYN(synchronous建立联机)
SYN置1就表示这是一个连接请求或连接接受报文, -
ACK(acknowledgement 确认)
TCP协议规定,只有ACK=1时有效,也规定建立 TCP 连接后,所有报文段都必须把 ACK 字段置为 1。 -
PSH(push传送)
-
FIN(finish结束)
-
RST(reset重置)
-
URG(urgent紧急)
TCP报文段首部格式
序号和确认号
seq:Sequence number(序号)
ack:Acknowledge number(确认号,小写,要区分与ACK,ACK是6个控制位之一,大小只有一位, 仅当 ACK=1 时ack字段才有效)
seq和ack大小均为4字节
服务器客户端状态
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT -在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED- 代表一个打开的连接,数据可以传送给用户;
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求;
CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
CLOSING -等待远程TCP对连接中断的确认;
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;
TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSED - 没有任何连接状态;
TCP三次握手
![](https://img.haomeiwen.com/i2246303/e21f153272323670.jpg)
1.客户进程也是先创建传输控制块,然后向B发出连接请求报文段,这时候首部中的同步位SYN=1,同时选择一个初始序号 seq=x。TCP规定,SYN报文段(SYN=1的报文段) 不能携带数据,但要消耗一个序号.声明自己的序号是 seq=x.这时,TCP客户进程进入SYN-SENT状态.
2.Server收到连接请求报文段后,如同意建立连接,则向A发送确认.在确认报文段中,应把SYN和ACK位都置1,确认号是ack=x+1(客户端seq+1),同时也为自己选择一个初始序号seq=y。这个报文段也不能携带数据,同样要消耗一个序号.这时TCP服务器进程进入SYN-RCVD(同步收到)状态.
3.客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,这种情况下,下一个数据报文段的序号仍是seq=x+1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。
当服务端收到客户端的确认后,也进入ESTABLISHED状态。
TCP四次挥手
- 客户端发送一个 FIN 标志位置为1的报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。 即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
- 服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 u +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。
即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
为什么断开链接的时候客户端设置的定时器时间等待要2MSL(两个通信报文的最大时间)?
- 为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
- 还可以防止已失效的报文段。客户端在发送最后一个ACK之后,再经过经过2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失。从保证在关闭连接后不会有还在网络中滞留的报文段去骚扰服务器。
- 如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 标志位置为1报文,且指定一个序列号w。此时服务端处于 LAST_ACK 的状态。
即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。 - 客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 w +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)后,客户端才进入CLOSED状态。
![](https://img.haomeiwen.com/i2246303/c5a289d2baa7ca54.png)
网友评论