2

我会用一个小例子来演示我面临的问题。

class TestProtocol(basic.LineReceiver):
    def lineReceived(self, line):
        print line

只要我使用 telnet 客户端连接到服务器,一切正常。但是,使用netcat连接并发送数据时没有收到该行。我有一种感觉,这与扭曲的默认分隔符“\r\n”有关。

我如何制作一个服务器,以便客户端(telnet 和 nc)在连接到客户端时都以类似的方式运行?

4

3 回答 3

4

LineReceiver仅支持一个分隔符。您可以指定它,但一次只能有一个。一般来说,如果你想支持多个分隔符,你需要实现一个支持它的新协议。您可以查看LineReceiver 的实现,了解有关如何实现基于行的协议的一些想法。

netcat 发送您键入的任何内容,因此分隔符通常为 \n (但它可能因平台和终端仿真器而异)。对于 \n 的特殊情况,它是默认分隔符的子字符串,您可以使用另一个技巧。设置to然后去掉传递给的行尾(如果有的话)。LineReceiver\r\nTestProtocol.delimiter"\n""\r"lineReceived

class TestProtocol(basic.LineReceiver):
    delimiter = "\n"

    def lineReceived(self, line):
        print line.rstrip("\r")
于 2011-02-23T13:23:01.277 回答
3

另一种解决方法是nc-C交换机一起使用。

手册

-C 发送 CRLF 作为行尾

或如@CraigMcQueen建议的那样:

-c开关的插座( Ubuntu 软件包)。

于 2012-07-16T17:29:36.850 回答
0

Twisted 的LineReceiver并且LineOnlyReceiver只支持一个行尾分隔符。

这是 and 的代码UniversalLineReceiverUniversalLineOnlyReceiver它覆盖了dataReceived()支持通用行尾(CR+LF、CR 或 LF 的任意组合)的方法。使用正则表达式 object 检测换行符delimiter_re

请注意,它们会覆盖包含比我想要的更多代码的函数,因此如果底层 Twisted 实现发生更改,它们可能会中断。我已经测试过它们可以与 Twisted 13.2.0 一起使用。本质的变化是使用delimiter_re. split()re模块。

# Standard Python packages
import re

# Twisted framework
from twisted.protocols.basic import LineReceiver, LineOnlyReceiver

class UniversalLineReceiver(LineReceiver):
    delimiter_re = re.compile(br"\r\n|\r|\n")
    def dataReceived(self, data):
        """
        Protocol.dataReceived.
        Translates bytes into lines, and calls lineReceived (or
        rawDataReceived, depending on mode.)
        """
        if self._busyReceiving:
            self._buffer += data
            return

        try:
            self._busyReceiving = True
            self._buffer += data
            while self._buffer and not self.paused:
                if self.line_mode:
                    try:
                        line, remainder = self.delimiter_re.split(self._buffer, 1)
                    except ValueError:
                        if len(self._buffer) > self.MAX_LENGTH:
                            line, self._buffer = self._buffer, b''
                            return self.lineLengthExceeded(line)
                        return
                    else:
                        lineLength = len(line)
                        if lineLength > self.MAX_LENGTH:
                            exceeded = self._buffer
                            self._buffer = b''
                            return self.lineLengthExceeded(exceeded)
                        self._buffer = remainder
                        why = self.lineReceived(line)
                        if (why or self.transport and
                            self.transport.disconnecting):
                            return why
                else:
                    data = self._buffer
                    self._buffer = b''
                    why = self.rawDataReceived(data)
                    if why:
                        return why
        finally:
            self._busyReceiving = False

class UniversalLineOnlyReceiver(LineOnlyReceiver):
    delimiter_re = re.compile(br"\r\n|\r|\n")
    def dataReceived(self, data):
        """
        Translates bytes into lines, and calls lineReceived.
        """
        lines = self.delimiter_re.split(self._buffer+data)
        self._buffer = lines.pop(-1)
        for line in lines:
            if self.transport.disconnecting:
                # this is necessary because the transport may be told to lose
                # the connection by a line within a larger packet, and it is
                # important to disregard all the lines in that packet following
                # the one that told it to close.
                return
            if len(line) > self.MAX_LENGTH:
                return self.lineLengthExceeded(line)
            else:
                self.lineReceived(line)
        if len(self._buffer) > self.MAX_LENGTH:
            return self.lineLengthExceeded(self._buffer)
于 2015-01-07T02:42:43.453 回答