Python从Teln读取空字符

2024-09-29 06:23:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我用telnet连接到我的服务器,它用消息回答我,并且在每条消息的末尾附加了hex00(空字符),不能读取。我尝试了一遍又一遍地搜索,但似乎无法成功,一个简单的例子:

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

这将返回一个输出:

^{pr2}$

但是应该有类似的东西:

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

有没有办法得到这个字符串的结尾字符?如果故意漏掉字符,我能得到字节作为输出吗?在

00字符在那里:

tcpdump


Tags: fromimport服务器localhost消息connection字符telnet
2条回答

这段代码(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
:
:

然后由read_until调用进程_rawq

^{pr2}$

我还想接收空字符。在我的特殊情况下,它标志着多行消息的结束。在

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

FWIWhttps://support.microsoft.com/en-us/kb/231866状态:

Communication is established using TCP/IP and is based on a Network Virtual Terminal (NVT). On the client, the Telnet program is responsible for translating incoming NVT codes to codes understood by the client's display device as well as for translating client-generated keyboard codes into outgoing NVT codes.

The NVT uses 7-bit codes for characters. The display device, referred to as a printer in the RFC, is only required to display the standard printing ASCII characters represented by 7-bit codes and to recognize and process certain control codes. The 7-bit characters are transmitted as 8-bit bytes with the most significant bit set to zero. An end-of-line is transmitted as a carriage return (CR) followed by a line feed (LF). If you want to transmit an actual carriage return, this is transmitted as a carriage return followed by a NUL (all bits zero) character.

以及

Name     Code   Decimal Value   
Function NULL   NUL 0   No operation

当我试图使用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类的方法:

^{pr2}$

这就解决了我的问题。在

相关问题 更多 >