如何在Twisted中使用dataReceived?

use*_*743 2 python twisted

我已经使用Twisted实现了一个服务器程序.我正在使用basic.lineReceiver该方法dataReceived从多个客户端接收数据.此外,我protocol.ServerFactory用于跟踪连接的客户端.服务器向每个连接的客户端发送一些命令.根据服务器从每个客户端获取的响应,它(服务器)应该执行一些任务.因此,我想到的最佳解决方案是为收到的消息创建一个缓冲区作为python列表,每次服务器端的函数想知道客户端的响应时,它们访问缓冲区列表的最后一个元素(该客户).事实证明这种方法不可靠.第一个问题是,由于使用了TCP流,有时消息合并(我可以使用分隔符).其次,收到的消息有时不符合它们的顺序.第三,网络通信似乎太慢,因为当服务器最初尝试访问缓冲列表的最后一个元素时,列表为空(这表明缓冲区上的最后一条消息可能不是对上次发送的响应)命令).你能否告诉我dataReceived在上述问题中使用或等效的最佳选择是什么?先感谢您.

编辑1:答案 - 虽然我接受了@ Jean-Paul Calderone的回答,因为我当然从中学到了,我想补充一点,在我自己对Twisted文档的研究中,我了解到为了避免服务器通信延迟,应该return在dataReceived()或lineReceived()函数的末尾使用,这解决了我的问题的一部分.其余的,在答案中解释.

Jea*_*one 5

我已经使用Twisted实现了一个服务器程序.我使用basic.lineReceiver和dataReceived方法来接收来自多个客户端的数据.

这是一个错误 - 遗憾的是,在Twisted的许多协议实现中错误地使用继承所带来的常见错误是构建越来越复杂的行为的机制.使用时twisted.protocols.basic.LineReceiver,dataReceived回调不适合您. LineReceiver.dataReceived是一个实现细节LineReceiver.你的回调是LineReceiver.lineReceived. LineReceiver.dataReceived看起来它可能适合你 - 它不是以下划线或任何东西开头 - 但事实并非如此. dataReceived是如何LineReceiver从其运输中接收信息.它是公共方法之一IProtocol- 传输和解释通过该传输接收的数据的协议之间的接口.是的,我刚才说"公共方法".麻烦在于为了别人的利益而公开.这很令人困惑,也许并没有尽可能地传达.毫无疑问,这就是为什么它是一个常见问题.

事实证明这种方法不可靠.第一个问题是,由于使用了TCP流,有时消息合并(我可以使用分隔符).

使用dataReceived是为什么会发生这种情况. LineReceiver已经为您实现了基于分隔符的解析.这就是为什么它被称为"线"接收器 - 它接收由分隔符分隔的线.如果你覆盖lineReceived而不是dataReceived那么你将被调用哪个接收到的每一行,无论TCP如何拆分或将它们一起粉碎.

其次,收到的消息有时不符合它们的顺序.

TCP是一种可靠,有序,面向流的传输."Ordered"表示字节按照发送的顺序到达.换句话说,当你write("x"); write("y")保证接收器在收到"y"之前会收到"x"(他们可能在同一次呼叫中收到"x"和"y" recv()但是如果他们这样做,那么数据肯定是" xy"而不是"yx";或者他们可以在两次调用中接收两个字节recv(),如果他们这样做,第一个recv()肯定是"x",第二个肯定是"y",而不是相反).

如果字节看起来的顺序与您发送的顺序不同,那么可能会出现另一个错误,使其看起来像是发生了这种情况 - 但实际上并非如此.您的平台的TCP堆栈很可能非常接近无错误,特别是它可能没有TCP数据重新排序错误.同样,Twisted的这个区域经过了极好的测试,可能正常工作.这会在您的应用程序代码中留下错误或对您的观察结果进行误解.也许您的代码并不总是将数据附加到列表中,或者数据可能不按您期望的顺序发送.

另一种可能性是您正在讨论数据通过多个单独的TCP连接到达的顺序.TCP仅通过单个连接进行排序.如果您有两个连接,则很少(如果有)保证数据将通过它们到达的顺序.

第三,网络通信似乎太慢,因为当服务器最初尝试访问缓冲列表的最后一个元素时,列表为空(这表明缓冲区上的最后一条消息可能不是对上次发送的响应)命令).

什么定义"太慢"?网络和网络一样快.如果这对你来说不够快,那就找一块更胖的铜.听起来你在这里真正的意思是你的服务器有时希望数据在数据实际到达之前到达.但这并不意味着网络速度太慢,这意味着您的服务器没有正确的事件驱动.如果您正在检查缓冲区而未找到预期的信息,那是因为您在事件发生之前对其进行了检查,并告知您该信息的到达.这就是为什么扭曲了所有这些回调方法- ,,dataReceived 等.当被调用时,这是一个事件通知,告诉你,现在事情发生这就造成了线是可用的(并且,为方便起见,需要一个参数-一个对象代表现在可用的线).lineReceivedconnectionLostlineReceivedlineReceived

如果您有一些代码要在一行到达时运行,请考虑将该代码放在该lineReceived方法的实现中.这样,当它运行时(响应正在接收的线路),您可以100%确定您有一条线路可以运行.你也可以确定它会尽快运行(一旦线路到达),但不久就会运行.