select() 调用在调用 setblocking(False) 后仍然阻塞
select() call still blocking after call to setblocking(False)
我有这段服务器端代码:
def listen_on_port(self):
try:
running = True
HOST = '' # Symbolic name meaning all available interfaces
PORT = int(self.port) # Arbitrary non-privileged port
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen()
server_socket.setblocking(False) # non-blocking I/O
self.logger.info(f'listening on port {self.port}')
read_list = [server_socket]
while running:
try:
self.logger.info(f'calling select().')
readable, writable, errored = select.select(read_list, [], [])
self.logger.info(f'called select().')
for s in readable:
if s is server_socket:
client_socket, address = server_socket.accept()
read_list.append(client_socket)
self.logger.info(f"Connection from address = {address} client_socket is {client_socket}.")
else:
self.logger.info(f"going to call s.recv(). s is {s}")
try:
data = s.recv(1024)
self.logger.info(f"Got data = {data}.")
if 'terminate' in data.decode('utf-8'):
self.logger.info(f"terminating.")
running = False
except Exception as ex:
self.logger.info(f'error s.recv() ex={ex}.')
finally:
self.logger.info(f"closing socket. s = {s}.")
s.close()
read_list.remove(s)
except Exception as ex:
self.logger.info(f'Inside while True. error ex={ex}.')
raise ex
except Exception as ex:
self.logger.info(f'error ex={ex}.')
当我 运行 我的脚本时,我可以在我的日志文件中看到我的代码正在等待 ...
readable, writable, errored = select.select(read_list, [], [])
... 到 return。我的日志文件:
$ cat /tmp/test.log
doing port 50050
listening on port 50050
calling select().
我打电话给...
server_socket.setblocking(False) # non-blocking I/O
...但代码仍然阻塞。如果重要的话,我 运行 正在 mac(不是 Linux 系统)。
select
不关心套接字是否阻塞。如果要进行 non-blocking select
调用,需要指定超时值为 0:
readable, writable, errored = select.select(read_list, [], [], 0)
也就是说,您的代码并没有比阻塞更好的事情。指定 timeout=0
只会将您的 while running
循环变成 busy-wait.
我有这段服务器端代码:
def listen_on_port(self):
try:
running = True
HOST = '' # Symbolic name meaning all available interfaces
PORT = int(self.port) # Arbitrary non-privileged port
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen()
server_socket.setblocking(False) # non-blocking I/O
self.logger.info(f'listening on port {self.port}')
read_list = [server_socket]
while running:
try:
self.logger.info(f'calling select().')
readable, writable, errored = select.select(read_list, [], [])
self.logger.info(f'called select().')
for s in readable:
if s is server_socket:
client_socket, address = server_socket.accept()
read_list.append(client_socket)
self.logger.info(f"Connection from address = {address} client_socket is {client_socket}.")
else:
self.logger.info(f"going to call s.recv(). s is {s}")
try:
data = s.recv(1024)
self.logger.info(f"Got data = {data}.")
if 'terminate' in data.decode('utf-8'):
self.logger.info(f"terminating.")
running = False
except Exception as ex:
self.logger.info(f'error s.recv() ex={ex}.')
finally:
self.logger.info(f"closing socket. s = {s}.")
s.close()
read_list.remove(s)
except Exception as ex:
self.logger.info(f'Inside while True. error ex={ex}.')
raise ex
except Exception as ex:
self.logger.info(f'error ex={ex}.')
当我 运行 我的脚本时,我可以在我的日志文件中看到我的代码正在等待 ...
readable, writable, errored = select.select(read_list, [], [])
... 到 return。我的日志文件:
$ cat /tmp/test.log
doing port 50050
listening on port 50050
calling select().
我打电话给...
server_socket.setblocking(False) # non-blocking I/O
...但代码仍然阻塞。如果重要的话,我 运行 正在 mac(不是 Linux 系统)。
select
不关心套接字是否阻塞。如果要进行 non-blocking select
调用,需要指定超时值为 0:
readable, writable, errored = select.select(read_list, [], [], 0)
也就是说,您的代码并没有比阻塞更好的事情。指定 timeout=0
只会将您的 while running
循环变成 busy-wait.