4

代码

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
4

1 回答 1

2

就像其他人在评论中所说的那样,问题在于在 Unix-y 平台上,SO_REUSEADDR如果您希望能够关闭侦听套接字然后立即打开一个绑定到同一端口的新套接字,则必须设置套接字选项。

但是请注意,在 Windows 上,您永远不应设置该SO_REUSEADDR选项,因为在 Windows 上,您想要的行为默认启用,并被SO_REUSEADDR重新定义为“关闭安全性”选项。

trio.socket非常底层并且暴露了所有这些细节,所以如果你想自己处理它们,它可以让你这样做。但是大多数用户最好使用更高级别的助手,比如trio.serve_tcp,它会自动处理很多这些细节。

于 2020-03-11T03:30:59.320 回答