TCP state transitions

TCP state transition diagram

image

image

Handwriting state transition diagram

image

First, the server status changes:

After the call server function to create a socket listen socket is a socket with an active converter is a passive socket is not connected, it instructs the kernel should accept the connection request directed to the socket, the socket state CLOSE conversion as LISTEN, waiting for client connections. Therefore, the server is connected to a passive receiver, the server will receive the SYN, will immediately send after receiving a SYN + ACK (with a message), then state transitions to the client and waits SYN_RCVD the ACK reply, at this time sets sockets in an incomplete connection queue, if an ACK is received status transitions to ESTABLISHED, connector sockets in the queue has been completed, it is noted that a connection queue uncompleted and completed a connection queue can not exceed the set maximum listen connector number. At this point the server and client can exchange data, the data after the client after receiving sockets active close, then the server will receive and respond to the ACK FIN, the state transitions to LOSE_WAIT, when the application layer is also close the server socket the server will happen when a word FIN state to LAST_ACK then the client will receive a reply ACK, the state transitions to CLOSED.

Second, the client transitions:

The client will connect the server After creating a socket, then the client sends a SYN to the server, and SYN_SENT state to wait for the server's reply, received server response SYN + ACK (with a message) after in this case the client will return ACK state to ESTABLISHED, after the completion of the normal data exchange will close client socket sends a FIN message at this time, the state transitions to FIN_WAIT_1, while waiting for reply to the server, in which case there are three cases:

(1) receives an ACK, but the server is not closed at this time server socket. The state transitions to the FIN_WAIT_2, and then waits for the server socket issued FIN off, then the reply is received if after automatically converted to the ACK, TIME_WAIT state to state, waiting for the timeout 2MSL CLOSED state.

(2) server while also close the socket, then the client receives SYN and ACK issue, state to CLOSING, after waiting for the server to reply ACK, ACK if received the go TIME_WAIT state.

(3)服务器在收到客户端FIN之后立马关闭套接字,此时客户端会收到一个ACK和FIN并发出ACK,状态​转换到TIME_WAIT状态。

以上提到的是一般正常的情况的TCP状态转换,当然还有很多异常情况这里不再一一描述,值得一提的是​ESTABLISHED状态之后,服务端也可以主动close套接字,转换到FIN_WAIT_1状态,此时服务端和客户端的状态转换就正好和上面描述相反了。

三、同时打开

同时打开时两端几乎在同时发送SYN,并进入SYN_SENT状态。当某一端收到SYN时,状态变为SYN_RCVD状态,收到SYN之后发出SYN+ACK,当双方都收到对端发送的SYN+ACK之后,套接字进入ESTABLISHED状态。同时打开链接需要交换4个报文比正常的3次握手多一个,而且双方既是客户端也是服务器,此种情况为双方同时connect对端。

四、同时关闭

同时关闭时双方都是主动关闭,双方状态变迁一样。以某一方为例:发送一个FIN,进入FIN_WAIT_1状态,接收一个FIN​同时发送一个ACK进入CLOSING状态,最后接收到对方回复的ACK进入TIME_WAIT状态。

TIME_WAIT

TIME_WAIT 是主动关闭链接时形成的,等待2MSL时间,约4分钟。主要是防止最后一个ACK丢失。 由于TIME_WAIT 的时间会非常长,因此server端应尽量减少主动关闭连接

存在TIME-WAIT状态有两个理由:
    1.实现终止TCP全双工连接的可靠性
    2.允许老的重复分节在网络中消逝
第一个理由:
假设最终的响应ACK丢失,服务器将重发最终的FIN,因此客户必须维护状态信息以允许它重发最终的ACK。如果不维护状态信息,它将响应以RST(另外一个类型的TCP分节),而服务器则把该分节解释成一个错误。如果TCP打算执行所有必要的工作以彻底终止某个连接上两个方向的数据流(即全双工关闭),那么它必须正确处理连接终止序列四个分节中任何一个分节的丢失情况。本例子也说明执行主动关闭的一端为什么进入TIME_WAIT状态,因为它可能不得不重发最终的ACK。
第二个理由:
我们假设206. 62. 226. 33端口1500和198. 69.10.2端口21之间有一个TCP连接。我们关闭这个连接后,在以后某个时候又重新建立起相同的IP地址和端口之间的TCP连接。后一个连接称为前一个连接的化身(incar-nation).因为它们的IP地址和端口号都相同。TCP必须防止来自某个连接的老重复分组在连接终止后再现,从而被误解成属于同一连接的化身。要实现这种功能,TCP不能给处于TIME-WAIT状态的连接启动新的化身。既然TIME-WAIT状态的持续时间是2MLS,这就足够让某个方向上的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MSL秒也被丢弃。通过实施这个规则,我们就能保证当成功建立一个TCP连接时,来自该连接先前化身的老重复分组都已在网络中消逝。

CLOSE_WAIT

CLOSE_WAIT是被动关闭连接是形成的。根据TCP状态机,服务器端收到客户端发送的FIN,则按照TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果服务器端不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。此时,可能是系统忙于处理读、写操作,而未将已收到FIN的连接,进行close。此时,recv/read已收到FIN的连接socket,会返回0。

常见面试题

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP is also a keep-alive timer, apparently, a client if a failure occurs, the server can not keep on waiting, wasted resources. Each time the server receives the client's request will reset the timer set time is usually 2 hours, if two hours has not received any data from the client, the server sends a detection message segment, then every 75 seconds to send one. If sending 10 consecutive probe packets still did not respond, the server brought out customers considered a failure, and then they close the connection.

Guess you like

Origin www.cnblogs.com/WindSun/p/11404802.html