Python读取直到来自Telnet的null字符

时间:2014-10-01 07:21:49

标签: python telnet telnetlib null-character

我正在telnet到我的服务器,它用消息回复我,并在每条消息的末尾附加了无法读取的hex00(空字符)。我试图通过搜索,但似乎无法使它工作,一个简单的例子:

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

返回输出:

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

然而应该像......那样:

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

有没有办法让这个字符串字符结束?如果故意错过角色,我可以将字节作为输出吗?

00字符在那里:

tcpdump

2 个答案:

答案 0 :(得分:1)

此代码(http://www.opensource.apple.com/source/python/python-3/python/Lib/telnetlib.py)似乎只是忽略空字符。这是非常正确的行为吗?

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()
    :
    :

我也想收到空字符。在我的特定情况下,它标记了多行消息的结束。

所以答案似乎是在编写库代码时这是预期的行为。

FWIW https://support.microsoft.com/en-us/kb/231866声明:

  

使用TCP / IP建立通信,并基于网络   虚拟终端(NVT)。在客户端,Telnet程序是   负责将传入的NVT代码转换为理解的代码   客户端的显示设备以及翻译   客户端生成的键盘代码为传出的NVT代码。

     

NVT使用7位代码表示字符。显示设备,简称   作为RFC中的打印机,只需要显示标准   打印由7位代码表示的ASCII字符并进行识别   并处理某些控制代码。 7位字符是   以8位字节发送,最高有效位设置为零。   行尾作为回车符(CR)发送,然后是a   换行(LF)。如果要传输实际的回车,   这是作为回车后跟NUL(所有位)传输的   零)角色。

Name     Code   Decimal Value   
Function NULL   NUL 0   No operation

答案 1 :(得分:1)

当我尝试使用telnet从RS232-TCP / IP转换器获取数据时,我偶然发现了同样的问题 - telnetlib会抑制消息中的每个0x00。正如Fredrik Johansson所说,这是telnetlib实施的方式。

一种解决方案是覆盖telnetlib的Telnet类中的process_rawq()函数,它不会占用所有空字符:

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

这解决了我的问题。