TCP中的三次握手,四次挥手是我们所熟知的,可是,我们熟悉里面的各种状态吗???
(SYN_SENT, ESTABLISHED, CLOSE_WAIT.............),试问一句,我们了解里面的状态转化吗???
1,大家先看一个简单的通信图(图片转载与:UNIX网络编程,page:36,图2-5)
可以很明显的看到,在通信双方,客户端,服务端的状态变化过程
有人可能会说:我们上面不是说,有11中状态吗??为什么到啦这里变成了只有10中
(1,(主动打开:SYN_SENT) 2,ESTABLISHED 3,(主动关闭:FIN_WAIT_1) 4,FIN_WAIT_2
5,TIME_WAIT 6,SYN_RCVD 7,CLOSE_WAIT(被动关闭) 8,LAST_ACK 9,CLOSED
10,LISTEN)
为什么不是11个呢???
哈哈,其实还有一种状态叫做:CLOSING(这个状态产生的原因比较特殊,后面分析)
接下来我们分析一下,这些状态的变化过程,,,
主动套接口:用来发起连接 被动套接口:用来接受连接
1,对于服务器端来说:
当调用socket函数创建一个套接字时,状态是CLOSED,它被假设为一个主动套接字,也就是说,它是一个
将调用connect发起连接的客户套接字。listen函数把一个未连接的套接字转化成一个被动套接字,指示内核
应接受指向该套接字的连接请求。结合TCP的状态转化图:
调用listen函数导致套接字从:CLOSED状态转化为:LISTEN状态
2,对于客户端来说:
调用socket函数创建一个套接口时,状态也是CLOSED,同样的,它也被假设为一个主动套接字,紧接着,调
用connect主动打开套接口,并且一直阻塞着,等待三次握手的完成,我们把这个状态称之为:主动套接口。
当客户端发起了三次握手的第一次(SYN J,MSS = 536)的时候,套接口的状态变成了:
SYN_SENT(主动打开)
3,对于服务器端而言,调用了listen之后,然后状态就变成了LISTEN状态,接着调用accept函数,使自身一直
保持阻塞的状态,直到三次握手的第一次来到(来自TCP协议栈的TCP的第一个分节),即接收到(SYN J,
MSS = 536),此刻状态由:LISTEN转变为SYN_RCVD
4,对于客户端来说,刚才发送了TCP协议栈中TCP三次握手的第一个分节,此刻应该接受来自服务器发送过来的
TCP三次握手的第二个分节,这时服务器发送过来:(SYN K, ACK J+1, MSS = 1460),此刻,服务器
的状态不变,还是SYN_RCVD,然后,客户端接受服务器发送过来的TCP三次握手的第二次分节,此刻状态
由之前的:SYN_SENT转变为ESTABLISHED,(客户端已经建立完成),这时,connect函数返回
5,然后客户端保持ESTABLISHED状态,并且发出TCP协议栈中TCP三次握手的第三个分节(ACK K+1)
服务端的状态由:SYN_RCVD转变为:ESTABLISHED,从未完成的队列中取出队首的第一个连接放在已完成
队列,这样accept函数就会返回。
此刻,两者都建立完成,这个时候可以完成通信了
6,那么接下来就是连接终止的四次握手,,,
当双方都变成ESTABLISHED状态之后,双方就可以通信了,在双方通信的过程中,由于状态都没有变化,
所以这里,我们暂且不讨论。在通信的时候呢,双方都可以主动发起关闭,那么:我们假定客户端发起一个
关闭请求(调用close函数):会向服务端发送一个TCP分节(TCP协议栈中四次握手的的第一个分节:
FIN M),然后客户端的状态会变成:FIN_WAIT_1(主动关闭),此刻,服务端接收到这个TCP分节后,
并且会对刚才发过来的连接进行确认(ACK M+1),,服务端的状态会变成 CLOSE_WAIT(被动关
闭),当,客户端接收到这个确认之后(ACK M+1),客户端的状态转变
为:FIN_WAIT_2 , 只有当服务端的read函数返回为0的时候,服务端才需要,也是才可以发起关闭请求(FIN