0

我目前正在构建一个 TCP 服务器(该服务器将由我的公司使用,因此它必须处于高生产水平)

我的要求是:

  1. 服务器会很快(它可以同时处理大量请求,因为我们的客户端会定期发送大文件,这会造成瓶颈)。

  2. 服务器将易于维护。

  3. 同时支持尽可能多的用户。

  4. 该服务器将是一个TCP服务器,因为它接收我们公司开发的协议消息,我需要自己解析它。

在检查了选项之后,我选择了 Python Twisted,因为他似乎满足了第一个要求(而且由于他在 Python 中,所以第二个要求自己解决了)。

在阅读了 Twisted 的文档后,我想到了一个我还没有找到优雅答案的问题,我的客户向我发送了相当大的数据包,我在这些数据包中做出基于子序列的决策。

假设我有 1000 个全为零的第一个字节,然后是另外 5,000 个全为 0x10 的字节,我将发回“Hello world”,如果我得到 2000 个全为 0x50 的字节,我将回答“大家好” .

我对 Twisted 的问题是数据最终会到达“protocol.Protocol”,并使用“dataReceived(self,data)”函数处理它们,而这一瞬间是一次性瞬间,这意味着如果我只得到一些第一次获取字节,我将在第二次获取其余字节我不知道如何从第一次保存数据......

我无法将数据保存在协议工厂中,因为我将同时与多个客户端交谈,然后一个将使用另一个客户端的数据,出于同样的原因,我不能使用 Globals。

我很确定我不是第一个遇到这个问题的人,我已经看到了几个在线解决方案,其中包括重新实现“protocol.Protocol”,它们真的不优雅..

有没有一种简单而优雅的方法来解决这个问题?(解决方案必须很优雅,因为我在它上面添加了多线程,因为我回馈给客户端的东西远不止“Hello World”而且我不想阻塞服务器)

顺便说一句,如果有经验的人可以为我推荐比 Twisted 更好的解决方案,我会非常高兴。

谢谢

洋子

4

1 回答 1

1

听起来您需要为每个连接状态维护一些。这是您可以存储并仍然使用此类协议的最低数量。您的协议类应该在每个连接中实例化一次,因此您应该能够使用该类上的属性来存储诸如zeros_received和之类的东西twos_received

def dataReceived(self, data):
    if self.zeros_received != 1000:
        for x, b in enumerate(data):
            if b != 0x00:
                # Handle unexpected byte error
            self.zeros_received += 1

            if self.zeros_received == 1000:
                break

    if self.twos_received != 5000:
        for b in data[x+1:]:
            if b != 0x10:
                # handle unexpected byte error
            self.twos_received += 1

            if self.twos_received == 5000:
                break

   # send hello...

一个更简单的解决方案是缓冲来自客户端的数据,然后阻塞(连接超时),直到您收到前 6k 字节。我会小心过早优化。您现在假设这将是您的瓶颈,但您的假设通常可能是错误的。首先实施一个简单的解决方案(使用缓冲读取器),然后对速度/内存使用情况进行基准测试,看看实际需要改进的地方。

def dataReceived(self, data):
    self.data += data

    if len(self.data) >= 6000:
        assert all(lambda b: b == 0x00, self.data[:1000]), 'expected 0x00'
        assert all(lambda b: b == 0x10, self.data[1000:6000]), 'expected 0x10'

        # send hello
于 2018-01-20T20:18:47.347 回答