Getting OSError: (Address already in use) while runnning a function that uses trio-sockets in a while loop
Getting OSError: (Address already in use) while runnning a function that uses trio-sockets in a while loop
代码
import trio
from trio import socket
async def listen(host, port):
while True:
fullmsg = ""
sock = socket.socket()
await sock.bind((host, port))
sock.listen()
print(f'Awaiting Receive On {host}:{port}')
conn, addr = await sock.accept()
print(f'Connection Received From {addr[0]}:{addr[1]}')
while True:
try:
msg = await conn.recv(8)
if len(msg.decode().strip()) > 0:
print(f'Received {len(msg.strip())} bytes')
fullmsg += msg.decode().strip()
else:
break
except Exception as e:
print(f'DEBUG: {e}')
sock.shutdown(0)
sock.close()
print(fullmsg)
# function that runs the listen function:
async def create():
async with trio.open_nursery() as nursery:
nursery.start_soon(listen, '127.0.0.1', 6969)
# To run the program
trio.run(create)
我想 运行 函数在每次收到长度为 0 的消息或客户端关闭连接但函数完成第一个 while 循环的第一次迭代时一遍又一遍,它给出了一个 OSError 说端口已经在使用中。我在循环结束时关闭并关闭了我的套接字,但我仍然不知道程序在哪里出错。
程序的输出
Awaiting Receive On 127.0.0.1:6969
Connection Received From 127.0.0.1:37122
Received 8 bytes
Received 5 bytes
Hello, World!
Traceback (most recent call last):
File "./ape.py", line 68, in <module>
trio.run(create)
File "/usr/local/lib/python3.8/dist-packages/trio/_core/_run.py", line 1804, in run
raise runner.main_task_outcome.error
File "./ape.py", line 59, in create
nursery.start_soon(listen, '127.0.0.1', 6969)
File "/usr/local/lib/python3.8/dist-packages/trio/_core/_run.py", line 730, in __aexit__
raise combined_error_from_nursery
File "./ape.py", line 15, in listen
await sock.bind((host, port))
File "/usr/local/lib/python3.8/dist-packages/trio/_socket.py", line 473, in bind
return self._sock.bind(address)
OSError: [Errno 98] Address already in use
就像其他人在他们的评论中所说的那样,问题是在 Unix-y 平台上,如果你想关闭一个监听套接字然后立即打开一个套接字,你必须设置 SO_REUSEADDR
套接字选项新的绑定到同一个端口。
请注意,在 Windows 上,您永远不应该设置 SO_REUSEADDR
选项,因为在 Windows 上,您想要的行为是默认启用的,并且 SO_REUSEADDR
被重新定义为 "turn off security" 选项。
trio.socket
非常低级并公开了所有这些细节,因此如果您想自己处理它们,它可以让您这样做。但是大多数用户最好使用像 trio.serve_tcp
这样的更高级别的助手,它会自动处理很多这些细节。
代码
import trio
from trio import socket
async def listen(host, port):
while True:
fullmsg = ""
sock = socket.socket()
await sock.bind((host, port))
sock.listen()
print(f'Awaiting Receive On {host}:{port}')
conn, addr = await sock.accept()
print(f'Connection Received From {addr[0]}:{addr[1]}')
while True:
try:
msg = await conn.recv(8)
if len(msg.decode().strip()) > 0:
print(f'Received {len(msg.strip())} bytes')
fullmsg += msg.decode().strip()
else:
break
except Exception as e:
print(f'DEBUG: {e}')
sock.shutdown(0)
sock.close()
print(fullmsg)
# function that runs the listen function:
async def create():
async with trio.open_nursery() as nursery:
nursery.start_soon(listen, '127.0.0.1', 6969)
# To run the program
trio.run(create)
我想 运行 函数在每次收到长度为 0 的消息或客户端关闭连接但函数完成第一个 while 循环的第一次迭代时一遍又一遍,它给出了一个 OSError 说端口已经在使用中。我在循环结束时关闭并关闭了我的套接字,但我仍然不知道程序在哪里出错。
程序的输出
Awaiting Receive On 127.0.0.1:6969
Connection Received From 127.0.0.1:37122
Received 8 bytes
Received 5 bytes
Hello, World!
Traceback (most recent call last):
File "./ape.py", line 68, in <module>
trio.run(create)
File "/usr/local/lib/python3.8/dist-packages/trio/_core/_run.py", line 1804, in run
raise runner.main_task_outcome.error
File "./ape.py", line 59, in create
nursery.start_soon(listen, '127.0.0.1', 6969)
File "/usr/local/lib/python3.8/dist-packages/trio/_core/_run.py", line 730, in __aexit__
raise combined_error_from_nursery
File "./ape.py", line 15, in listen
await sock.bind((host, port))
File "/usr/local/lib/python3.8/dist-packages/trio/_socket.py", line 473, in bind
return self._sock.bind(address)
OSError: [Errno 98] Address already in use
就像其他人在他们的评论中所说的那样,问题是在 Unix-y 平台上,如果你想关闭一个监听套接字然后立即打开一个套接字,你必须设置 SO_REUSEADDR
套接字选项新的绑定到同一个端口。
请注意,在 Windows 上,您永远不应该设置 SO_REUSEADDR
选项,因为在 Windows 上,您想要的行为是默认启用的,并且 SO_REUSEADDR
被重新定义为 "turn off security" 选项。
trio.socket
非常低级并公开了所有这些细节,因此如果您想自己处理它们,它可以让您这样做。但是大多数用户最好使用像 trio.serve_tcp
这样的更高级别的助手,它会自动处理很多这些细节。