витой сервер, клиент nc - PullRequest
2 голосов
/ 23 февраля 2011

Я продемонстрирую проблему, с которой сталкиваюсь, на небольшом примере.

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

Все работает нормально, пока я использую клиент telnet для подключения к серверу.Однако по линии не получено подключение и отправка данных с помощью netcat.У меня такое ощущение, что это как-то связано с разделителем по умолчанию, который в витой форме "\ r \ n".

Как я могу сделать сервер таким, чтобы оба клиента (telnet и nc) вели себя вАналогичным образом при подключении к клиенту?

Ответы [ 3 ]

4 голосов
/ 23 февраля 2011

LineReceiver поддерживает только один разделитель. Вы можете указать это, но может быть только один за один раз. В общем, если вы хотите поддерживать несколько разделителей, вам необходимо реализовать новый протокол, который поддерживает это. Вы можете взглянуть на реализацию LineReceiver для некоторых идей о том, как реализован линейный протокол.

netcat отправляет все, что вы вводите, поэтому разделитель часто \ n (но он может варьироваться от платформы к платформе и от эмулятора терминала до эмулятора терминала). Для особого случая \ n, который является подстрокой по умолчанию LineReceiver разделитель \r\n, есть еще один прием, который вы можете использовать. Установите TestProtocol.delimiter на "\n", а затем уберите "\r" с конца линии, переданной на lineReceived, если она есть.

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

    def lineReceived(self, line):
        print line.rstrip("\r")
3 голосов
/ 16 июля 2012

Другим обходным решением является использование nc с переключателем -C.

Из руководства :

-C Отправить CRLF как конец строки

или как @ CraigMcQueen предложил:

сокет с переключателем -c ( пакет Ubuntu ).

0 голосов
/ 07 января 2015

Twisted's LineReceiver и LineOnlyReceiver поддерживают только один разделитель строки.

Вот код для UniversalLineReceiver и UniversalLineOnlyReceiver, которые переопределяют метод dataReceived() с поддержкой универсальных окончаний строки (любая комбинация CR + LF, CR или LF). Обрывы строк обнаруживаются с помощью объекта регулярного выражения 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)
...