socket编程中主动关闭VS被动关闭
tcp中server,client都可能是主动关闭方或者被动关闭方,现阐述下两者之间的关系:
客户端(client) 服务器(server)
close() Fin x -> 读通道关闭(close_wait)
写通道关闭 <- Ack x+1
读通道关闭(time_wait) <- Fin y close()
ack y+1 -> 写通道关闭
2x msl closed
closed
1、 客户端是调用函数close(),这时,客户端会发送一个FIN给服务器。
2、 服务器收到FIN,关闭套接字读通道,并将自己状态设置为CLOSE_WAIT(表示被动关闭),
并返回一个ACK给客户端。
3、 客户端收到ACK,关闭套接字写通道
接下来,服务器会调用close():
1、 服务器close(),发送一个FIN到客户端。
2、 客户端收到FIN,关闭读通道,并将自己状态设置成TIME_WAIT,发送一个ACK给服务器。
3、 服务器收到ACK,关闭写通道,并将自己状态设置为CLOSE。
4、 客户端等待两个最大数据传输时间,然后将自己状态设置成CLOSED。
有了上面的背景知识,对于我们系统线上一个case分析就很简单了!
首先是主动关闭日志很多,后来是被动关闭的日志
由于server端发现了大量闲置的没有Io的socket连接,有监听器在监听是否存在闲置的socket连接,就释放并关闭这些连接,time_wait就出现了,这个时候应用方客户端重启应用,释放了资源包括一些客户端连接,这个时候close_wait出现了,正好是以上日志所反映的
同时time_wait状态的连接是不会释放内核资源,所以服务端不要轻易close!
socket中的read返回0
在socket中服务器与客户端进行通信,当其中一方调用close(即这一方会发送一个fin)关闭套接字之后,另一方read()会返回一个0。
我之前编写的一个服务器与客户端通信(一个服务器只连接一个客户端):服务器开两个进程,一个用于接收客户端发送的数据,另一个进程用于
向客户端发送数据。客户端开两个进程也是一个用于发送数据一个用于接收数据。由于创建了两个进程,那么套接字的引用计数都为2,只有当客户
端关闭两次套接字,在服务器的read()才会返回0
另外,如果在虚拟机上运行,打开两个shell,一个运行客户端,一个运行服务器,当关闭运行客户端的shell,则服务器的read()会返回0
python socket模块4种异常
-
与一般I/O和通信问题有关的socket.error;
-
与查询地址信息有关的socket.gaierror;
-
与其他地址错误有关的socket.herror;
-
与在一个socket上调用settimeout()后,处理超时有关的socket.timeout.