Socket编程示例05--非阻塞超时和连接断开
http://python.jobbole.com/81860/
https://docs.python.org/zh-cn/3/howto/sockets.html
https://codeday.me/bug/20171014/84020.html
https://stackoverrun.com/cn/q/4554555
https://stackoverflow.com/questions/3432102/python-socket-connection-timeout
https://stackoverflow.com/questions/45039993/python-socket-wont-timeout
https://stackoverflow.com/questions/11865685/handling-a-timeout-error-in-python-sockets
https://stackoverflow.com/questions/23642478/will-a-python-socket-timeout
https://stackoverflow.com/questions/34371096/how-to-use-python-socket-settimeout-properly
https://stackoverflow.com/questions/2719017/how-to-set-timeout-on-pythons-socket-recv-method
https://mozillazg.com/2013/11/python-socket-connect-set-timeout.html
https://www.programcreek.com/python/example/97/socket.error
https://code.i-harness.com/zh-CN/q/ff83c1
https://oomake.com/question/105624
https://blog.csdn.net/xhw88398569/article/details/47102187
https://stackoverflow.com/questions/15705948/python-socketserver-timeout
非阻塞超时
def receive_msg_from_client(self):
json_str = None
logging.info('Receive Client Message[{}, {}]...'.format(self.name, self.client_address))
if not self.abnormal_flag:
try:
req_msg = self.request.recv(st_config.SOCKET_RECEIVE_BUFFER).decode(encoding='utf-8')
except socket.timeout as err:
logging.warning('Receive Client Message Error[{}, {}]: "{}"'.format(self.name, self.client_address, err))
except socket.error as err:
logging.warning('Receive Client Message Error[{}, {}]: "{}"'.format(self.name, self.client_address, err))
self.abnormal_flag = True
except Exception as err:
logging.warning('Receive Client Message Error[{}, {}]: "{}"'.format(self.name, self.client_address, err))
self.abnormal_flag = True
else:
if req_msg:
logging.info('Receive Client Message[{}, {}]: {}'.format(self.name, self.client_address, req_msg))
try:
json_str = json.loads(req_msg)
except BaseException as err:
logging.warning('JSON Load Error[{}, {}]: "{}"'.format(self.name, self.client_address, err))
else:
# 如果req_msg为空,则表示连接断开
logging.warning('Network Abnormal[{}, {}]: Disconnect'.
format(self.name, self.client_address, req_msg))
self.abnormal_flag = True
return json_str
阻塞与非阻塞超时
In the case of a non blocking socket that has no data available, recv will throw the socket.error exception and the value of the exception will have the errno of either EAGAIN or EWOULDBLOCK. Example:
import sys
import socket
import fcntl, os
import errno
from time import sleep
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
fcntl.fcntl(s, fcntl.F_SETFL, os.O_NONBLOCK)
while True:
try:
msg = s.recv(4096)
except socket.error, e:
err = e.args[0]
if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
sleep(1)
print 'No data available'
continue
else:
# a "real" error occurred
print e
sys.exit(1)
else:
# got a message, do something :)
The situation is a little different in the case where you've enabled non-blocking behavior via a time out with socket.settimeout(n)
or socket.setblocking(False)
. In this case a socket.error is stil raised, but in the case of a time out, the accompanying value of the exception is always a string set to 'timed out'. So, to handle this case you can do:
import sys
import socket
from time import sleep
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
s.settimeout(2)
while True:
try:
msg = s.recv(4096)
except socket.timeout, e:
err = e.args[0]
# this next if/else is a bit redundant, but illustrates how the
# timeout exception is setup
if err == 'timed out':
sleep(1)
print 'recv timed out, retry later'
continue
else:
print e
sys.exit(1)
except socket.error, e:
# Something else happened, handle error, exit, etc.
print e
sys.exit(1)
else:
if len(msg) == 0:
print 'orderly shutdown on server end'
sys.exit(0)
else:
# got a message do something :)
As indicated in the comments, this is also a more portable solution since it doesn't depend on OS specific functionality to put the socket into non-blockng mode.
See recv(2) and python socket for more details.