2014-10-01 71 views
1

我正在telneting到我的服務器,它回答我的消息,並在每封郵件的末尾附加hex00(空字符),無法讀取。我試圖通過,並通過搜索,但似乎無法使其工作,一個簡單的例子:Python直到從Telnet空字符

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

回答

1

我在這個同樣的問題絆倒試圖使用telnet從RS232-TCP/IP轉換器獲得數據時 - 在telnetlib會從消息打壓每一個爲0x00。正如Fredrik Johansson所回答的那樣,這是telnetlib的實施方式。

一個解決辦法是覆蓋從telnetlib的遠程登錄類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 

這爲我解決了這個問題。

0

我不能添加評論,因爲我有< 50聲譽。 您是否試過read_until("")read_all()?你能在這種情況下捕捉到失蹤的人物嗎?

+0

我已經嘗試過它們,但它們不是解決方案。當我使用它們時,我必須設置超時,在這種情況下,這些方法每次都等待超時通過,這在發送大量數據時效率不夠高。在超時之後,他們仍然有可能無法獲得迴應。 如果沒有設置超時,它會阻止未知時間的連接。 – brian 2014-10-01 10:22:56

+0

我想你可以在read_until(... timeout = timeout)上設置超時時間。 在源文件中,它基本上使用'find'作爲匹配,所以只是想知道read_until(「\ x00」)應該工作。 – Anzel 2014-10-01 10:25:33

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)的形式發送,然後是換行符(LF) 。如果你想發送一個實際的回車, 這是作爲一個回車後跟一個NUL(所有位 爲零)字符發送。

Name  Code Decimal Value 
Function NULL NUL 0 No operation 
相關問題