0

我最近完成了一个混合使用 Django 和 Twisted 的项目,并意识到它对于我需要的东西来说太过分了,这基本上只是我的服务器通过 TCP 套接字进行通信的一种方式。我转向三重奏,到目前为止,我喜欢我所看到的,因为它更直接(对于我需要的)。尽管如此,我只是想确保我以正确的方式做这件事。

我遵循了教授基础知识的教程,但我需要一个可以同时处理多个客户端的服务器。为此,我想出了以下代码

import trio
from itertools import count

PORT = 12345
BUFSIZE = 16384
CONNECTION_COUNTER = count()


class ServerProtocol:

    def __init__(self, server_stream):
        self.ident = next(CONNECTION_COUNTER)
        self.stream = server_stream

    async def listen(self):
        while True:
            data = await self.stream.receive_some(BUFSIZE)
            if data:
                print('{} Received\t {}'.format(self.ident, data))
                # Process data here


class Server:

    def __init__(self):
        self.protocols = []

    async def receive_connection(self, server_stream):
        sp: ServerProtocol = ServerProtocol(server_stream)
        self.protocols.append(sp)
        await sp.listen()


async def main():
    await trio.serve_tcp(Server().receive_connection, PORT)

trio.run(main)

我的问题似乎是每个周期都在每个周期ServerProtocol运行listen,而不是等待数据可用。

在这种情况下,我感觉我使用 Trio 错误,是否有我遗漏的 Trio 最佳实践?

4

1 回答 1

2

你的整体结构在我看来很好。我跳出来的问题是:

    while True:
        data = await self.stream.receive_some(BUFSIZE)
        if data:
            print('{} Received\t {}'.format(self.ident, data))
            # Process data here

做出的保证receive_some是:如果对方已经关闭了连接,那么它会立即返回一个空的字节串。否则,它会等到有一些数据返回,然后将其作为非空字节串返回。

所以你的代码应该可以正常工作......直到另一端关闭连接。然后它开始执行无限循环,不断检查数据,返回一个空字节串 ( data = b""),因此该if data: ...块不会运行,它会立即循环以再次执行此操作。

解决此问题的一种方法是(最后 3 行是新的):

    while True:
        data = await self.stream.receive_some(BUFSIZE)
        if data:
            print('{} Received\t {}'.format(self.ident, data))
            # Process data here
        else:
            # Other side has gone away
            break
于 2019-05-09T00:31:35.247 回答