1

私は自分のサーバーに telnet で接続しています。サーバーはメッセージで応答し、各メッセージの最後に読み取れない hex00 (ヌル文字) が追加されます。私は徹底的に検索しようとしましたが、それを機能させることができないようです.簡単な例:

from telnetlib import Telnet
connection = Telnet('localhost', 5001)
connection.write('aa\n')
connection.read_eager()

これは出力を返します:

'Fail - Command aa not found.\n\r'

一方、次のようなsthがあるはずです:

'Fail - Command aa not found.\n\r\0'

この文字列の終わりを取得する方法はありますか? 文字が意図的に欠落している場合、出力としてバイトを取得できますか?

00 文字があります。

tcpdump

4

2 に答える 2

2

telnet を使用して RS232-TCP/IP コンバーターからデータを取得しようとしたときに、これと同じ問題に遭遇しました。telnetlib は、メッセージからすべての 0x00 を抑制します。Fredrik Johansson がよく答えたように、それは telnetlib が実装された方法です。

process_rawq()解決策の 1 つは、ヌル文字をすべて消費しない telnetlib の Telnet クラスの関数をオーバーライドすることです。

import telnetlib
from telnetlib import IAC, DO, DONT, WILL, WONT, SE, NOOPT

def _process_rawq(self):
    """Alteração da implementação desta função necessária pois telnetlib suprime 0x00 e \021 dos dados lidos
    """
    buf = ['', '']
    try:
        while self.rawq:
            c = self.rawq_getchar()
            if not self.iacseq:
#                if c == theNULL:
#                    continue
#                if c == "\021":
#                    continue
                if c != IAC:
                    buf[self.sb] = buf[self.sb] + c
                    continue
                else:
                    self.iacseq += c
            elif len(self.iacseq) == 1:
                # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
                if c in (DO, DONT, WILL, WONT):
                    self.iacseq += c
                    continue

                self.iacseq = ''
                if c == IAC:
                    buf[self.sb] = buf[self.sb] + c
                else:
                    if c == SB: # SB ... SE start.
                        self.sb = 1
                        self.sbdataq = ''
                    elif c == SE:
                        self.sb = 0
                        self.sbdataq = self.sbdataq + buf[1]
                        buf[1] = ''
                    if self.option_callback:
                        # Callback is supposed to look into
                        # the sbdataq
                        self.option_callback(self.sock, c, NOOPT)
                    else:
                        # We can't offer automatic processing of
                        # suboptions. Alas, we should not get any
                        # unless we did a WILL/DO before.
                        self.msg('IAC %d not recognized' % ord(c))
            elif len(self.iacseq) == 2:
                cmd = self.iacseq[1]
                self.iacseq = ''
                opt = c
                if cmd in (DO, DONT):
                    self.msg('IAC %s %d',
                        cmd == DO and 'DO' or 'DONT', ord(opt))
                    if self.option_callback:
                        self.option_callback(self.sock, cmd, opt)
                    else:
                        self.sock.sendall(IAC + WONT + opt)
                elif cmd in (WILL, WONT):
                    self.msg('IAC %s %d',
                        cmd == WILL and 'WILL' or 'WONT', ord(opt))
                    if self.option_callback:
                        self.option_callback(self.sock, cmd, opt)
                    else:
                        self.sock.sendall(IAC + DONT + opt)
    except EOFError: # raised by self.rawq_getchar()
        self.iacseq = '' # Reset on EOF
        self.sb = 0
        pass
    self.cookedq = self.cookedq + buf[0]
    self.sbdataq = self.sbdataq + buf[1]
telnetlib.Telnet.process_rawq = _process_rawq

次に、Telnet クラスのメソッドをオーバーライドします。

telnetlib.Telnet.process_rawq = _process_rawq

これで問題は解決しました。

于 2015-09-16T18:43:35.520 に答える
1

このコード ( http://www.opensource.apple.com/source/python/python-3/python/Lib/telnetlib.py ) は、null 文字を無視しているようです。それは本当に正しい行動ですか?

def process_rawq(self):
    """Transfer from raw queue to cooked queue.

    Set self.eof when connection is closed.  Don't block unless in
    the midst of an IAC sequence.

    """
    buf = ''
    try:
        while self.rawq:
            c = self.rawq_getchar()
            if c == theNULL:
                continue
:
:

次に、process_rawq が read_until などによって呼び出されます。

def read_until(self, match, timeout=None):
    """Read until a given string is encountered or until timeout.

    When no match is found, return whatever is available instead,
    possibly the empty string.  Raise EOFError if the connection
    is closed and no cooked data is available.

    """
    n = len(match)
    self.process_rawq()
    :
    :

null文字も受け取りたいです。私の特定のケースでは、複数行のメッセージの終わりを示します。

したがって、答えは、ライブラリ コードが記述されているため、これは予期される動作であると思われます。

FWIW https://support.microsoft.com/en-us/kb/231866は次のように述べています。

通信は TCP/IP を使用して確立され、Network Virtual Terminal (NVT) に基づいています。クライアントでは、Telnet プログラムは着信 NVT コードをクライアントのディスプレイ デバイスが理解できるコードに変換し、クライアントが生成したキーボード コードを発信 NVT コードに変換します。

NVT は文字に 7 ビット コードを使用します。RFC でプリンタと呼ばれるディスプレイ デバイスは、7 ビット コードで表される標準印刷 ASCII 文字を表示し、特定の制御コードを認識して処理することだけが必要です。7 ビット文字は、最上位ビットがゼロに設定された 8 ビット バイトとして送信されます。行末は、キャリッジ リターン (CR) とそれに続くライン フィード (LF) として送信されます。実際のキャリッジ リターンを送信する場合は、キャリッジ リターンの後に NUL (すべてのビットがゼロ) 文字が続く形で送信されます。

Name     Code   Decimal Value   
Function NULL   NUL 0   No operation
于 2015-09-15T17:37:46.957 に答える