首先先来了解以下TCP的特性:
- 有连接
- 可靠
- 面向字节流的
因为TCP是有连接的,所以为了保证TCP的连接正常,需要证明:
- 发送方的发送能力
- 发送方的接受能力
- 接收方的发送能力
- 接收方的接受能力
要证明上面的四个能力,TCP要经过三次握手来建立连接和并且要经过四次挥手断开连接
*三次握手详解
客户端和服务器端都没有创建的时候都处于colsed状态,当服务器端调用listen的时候,服务器端进入listen(监听状态),监听客户端有没有连接服务器端的请求,
当客户端调用connect()的时候,客户端的状态变成SYN_SENT状态,客户端给服务器端发送一个SYN(同步报文段)
服务器端接收到同步报文段的时候就变为SYN_RCVD状态,这个状态的时候相当于服务器端调用了accept()方法。此时会返回给客户端一个SYN和ACK(确认应答信息),客户端收到以后进入ESTABLISHED(经过三次握手之后的状态)状态,同时发送给服务器端一个ACK。最后服务器端进入ESTABLISHED状态。
举个例子:
下图是三次握手过程中可以证明的能力:
常见面试题
1.两次握手是否可以保证连接呢?
答案是不能,两次握手的过程中不能保证收发双方的发送能力和接收能力
2.四次握手是否可以保证连接
答案当然是可以的,三次都可以保证连接,四次当然可以,只是没有这个必要
*四次挥手详解(断开连接)
当客户端调用close()方法的之后(服务器端不能主动进行关闭),给服务器端发送一个FIN(结束报文段)(即将TCP头部信息当中的FIN标识为1),去告诉服务器端本端要进行关闭了,就从ESTABLISHED状态变成了FIN_WAIT_1状态,服务器接收到这个消息以后进入就从ESTABLISHED状态进入了CLOSE_WAIT状态,并给客户端发送一个ACK告诉客户端我收到了你的关闭请求了,客户端收到ACK以后从FIN_WAIT_1状态变成FIN_WAIT_2状态,等到服务器端处理完接收缓冲区的所有任务之后会调用close()方法(处理完所有的任务以后会从CLOSE_WAIT状态变成LAST_ACK),会给客户端发送一个FIN(标识为1)告诉客户端我已经执行完了所有的任务,可以关闭了,此时客户端变为TIME_WAIT状态,然后会给服务器端发送一个ACK确认应答信息,服务器端接收到以后进入CLOSED状态,客户端在两个最大等待时间内没有接收到服务器端发送过来的消息,则进入CLOSED状态。
常见面试题
1.TIME_WAIT 的时间为什么是2MSL?
- MSL是TCP报文的最大生存时间,因此TIME_WAIT持续存在2MSL的话
- 能保证在两个传输方向上的尚未被接收或者迟到的报文段都已经消失
- 在理论上保证最后一个报文可靠到达,假设最后一个ACK丢失,那么服务器会再重发一个FIN(结束报文),这时客户的进程虽然已经不再了,但是TCP连接还在,仍然可以重发LAST_ACK
- ** TIME_WAIT = 等ACK到对方(1MSL) + FIN最大发送时间(1MSL)**
2.三次挥手可不可以实现关闭?
答案是不一定,三次挥手能否正常关闭取决于服务器端的接收缓冲区中有没有缓存的信息,如果就收缓冲区中没有缓存的内容要执行,三次挥手就可以断开连接;如果接收缓冲区有缓存的内容要执行,则三次挥手不能断开连接,要等到接收缓冲区的任务全部执行完才可以关闭连接。
3.服务器出现大量CLOSE_WAIT
一般而言,服务器端出现大量的CLOSE_WAIT的话,原因就是服务器没有正确的关闭socket(程序没有调用close()方法),导致四次挥手没有正确完成。