一、tcp三次握手过程和四次挥手的过程?(计网)
TCP三次握手的过程如下。
TCP是面向连接的协议,所以使用TCP前必须先建立连接,而建立连接是通过三次握手来进行的。过程如下。
一开始,客户端和服务端都处于CLOSE状态,先是服务端主动监听某个端口,处于LISTEN状态
客户端会随机初始化序号(client-isn),将此序号置于TCP首部的【序号】字段中,同时把SYN标志位置为1,表示SYN报文。接着把第一个SYN报文发给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于SYN-SENT状态。
服务端收到客户端的SYN报文后,首先服务端也随机初始化自己的序号(sever-isn),将此序号填入TCP首部的【序号】字段中,其次把TCP首部的【确认应答号】字段填入client-isn+1,接着把SYN和ACK标志位置为1.最坏把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于SYN-RCVD状态。
客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文TCP首部ACK标志位置为1,其次【确认应答号】字段填入sever-sin+1,最后把报文发送给服务端,这次报文可携带客户到服务端的数据,之后客户端处于ESTABLISHED状态。
服务端收到客户端的应答报文后,也进入ESTABLISHED状态。
从上面的过程中可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的,这也是面试常问的问题。
一旦完成三次握手,双方都处于ESTABLISHED状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。
二、TCP四次挥手如下:
具体过程:
1.客户端主动调用关闭连接的函数,于是就会发送FIN报文,这个FIN报文代表客户端不会再发生数据了,进入FIN-WAIT-1状态;
2.客户端收到了FIN报文,然后马上回复一个ACK确认报文,此时服务端进入CLOSE-WAIT状态。在收到FIN报文的时候,TCP协议栈会为FIN包插入一个文件结束符EOF到接收缓冲区中,服务端应用程序可以通过read调用来感知这个FIN包,这个EOF会被放在已排队等候的其他已接收的数据之后,所以必须要得继续read接受缓冲区已接受的数据;
3.接着,当服务端在read数据时候,最后自然就会读到EOF,接着read()就会返回0,这是服务端应用程序如果有数据要发送的话,就发完数据后才调用关闭连接的函数,如果服务端应用程序没有数据要发送的话,可以直接调用关闭连接的函数,这时服务端就会发一个FIN包,这个FIN报文代表服务去不再发送数据了,之后处于LAST-ACK状态;
4.客户接收到服务端的FIN包,并发送ACK确认包给服务端,此时客户端将进入TIME-WAIT状态;
5.服务端收到ACK确认包后,就进入了最后的CLOSE状态;
6.客户端经过2MSL时间之后,也进入了CLOSE状态;
三、TCP为什么要四次挥手,三次不行嘛?
服务器收到客户端的FIN报文时,内核会马上回一个ACK应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送FIN报文,而是将发送FIN报文的控制权交给服务端应用程序:
1.如果服务端应用程序有数据要发送的话,就发完数据之后,才调用关闭连接的函数;
2.如果服务端应用程序没有数据要发送的话,可以直接调用关闭连接的函数;
从上面的过程可知,是否要发送第三次挥手的控制权不在内核,二十在被动关闭方的应用程序,因为应用程序可能还有数据要发送,由应用程序决定什么时候调用关闭连接的函数,当调用了关闭连接的函数,内核就会发生FIN报文了,所以服务端的ACK和FIN一般都会分开发送。