详解socket模型和三次握手四次挥手过程

一、socket网络开发模型

  • 首先服务端创建一个socket对象,python中通过socket包创建。对象创建时,需要绑定它的IP地址族(IPv4或Ipv6)和协议(TCP或UDP)。  bind()绑定本机IP地址和端口号,listen()启动监听。至此服务端建立完成。
  • 客户端需要遵从与服务端一样的IP地址族和协议,请求服务器的IP地址和端口号。客户端自身会启动一个随机的端口号,并把这个端口号发送给服务端。
  • 服务器监听接收(accept())到客户端发送的请求,建立与客户端的连接(connect(),或叫握手)。
  • 连接建立后,客户端可以写入(write())数据到socket对象中,服务端可以读取(read())到客户端写入的数据。服务端处理数据后,可以写入(write())socket返回一个处理结果,客户端读取(read())到这个返回结果。
  • 客户端关闭(close())连接,客户端释放当前占用的客户端端口号。
  • 服务端收到客户端关闭消息后,关闭与客户端的连接。


二、 建立连接协议(TCP三次握手过程)

图片备注:红框表示socket在网络程序使用中的状态

三次握手过程:

  • 首先客户端创建socket对象,通过connect函数向服务端发起连接请求,发送的请求为包含SYN J的一个TCP报文,J为随机数值。客户端socket对象此时会处于SYN_SEND状态。
  • 服务端用accept函数接收客户端请求,并向客户端发送一个SYN K序列号和一个应答的ACK,ACK的值为客户端标示值加1。服务端此时会处于SYN_RECV状态。
  • 客户端connect函数收到服务端返回值后,会向服务端再发送一个ACK K+1应答序列,序列值为服务端应答ACK值加1。
  • 服务端accept函数收到返回值后,客户端和服务端socket对象状态都变为ESTABLISHED已连接状态。


三、连接终止协议(TCP四次挥手过程)

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,这里成为主动端,而另一方执行被动关闭,即被动端。

四次挥手过程:

1. 主动close一端会向被动端发送FIN终止信号序列,主动端状态变为FIN_WAIT_1。此时关闭了主动端向被动端的数据传输。

2. 被动端收到FIN后,向主动端发送一个ACK序列(值为FIN序号加1),完成发送后被动端状态置为CLOSE_WAIT,此时被动端向主动端的数据传输还没有关闭。

3. 主动端收到被动端发送的ACK响应序列,状态切换到FIN_WAIT_2。

4. 被动端关闭与客户端的连接,向主动端发送一个FIN终止信号序列,被动端状态会切换为LAST_ACK(最后一个响应状态)。

5. 主动端收到被动端发出的FIN,接着发送ACK响应序列到被动端,发送后主动端状态切换为TIME_WAIT。

6. 被动端收到ACK后,释放掉socket资源。

另一种情况(前2步和前面一样):

3. 主动端未收到被动端的ACK响应,而是收到了被动端的FIN终止信号,即被动端也正好发起了连接关闭操作,主动端状态会切换到CLOSING。

4. 此时主动端向被动端发送一个ACK响应,主动端状态切换为TIME_WAIT。

5. 被动端收到ACK后,释放掉socket资源。

四、socket状态说明

  • CLOSED:这个没什么好说的了,表示初始状态。
  • LISTEN表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
  • SYN_SENT表示客户端已发送SYN报文,发生在客户端SOCKET执行CONNECT连接时。
  • SYN_RECV 这个状态表示接受到了SYN报文。在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。
  • ESTABLISHED表示连接已经建立了。
  • FIN_WAIT_1当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,然后在等待对方的FIN报文。在实际的正常情况下,应为会马上回应ACK报文,所以FIN_WAIT_1状态比较短暂。
  • FIN_WAIT_2此状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
  • TIME_WAIT表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL(MSL即Maximum Segment Lifetime,是TCP片在网上的最长存活时间,2MSL表示240秒)后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
  • CLOSING这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
  • CLOSE_WAIT这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
  • LAST_ACK这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

原文链接:http://f.dataguru.cn/thread-109751-1-1.html

你可能感兴趣的:(详解socket模型和三次握手四次挥手过程)