我在這個同樣的問題絆倒試圖使用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
這爲我解決了這個問題。
我已經嘗試過它們,但它們不是解決方案。當我使用它們時,我必須設置超時,在這種情況下,這些方法每次都等待超時通過,這在發送大量數據時效率不夠高。在超時之後,他們仍然有可能無法獲得迴應。 如果沒有設置超時,它會阻止未知時間的連接。 – brian 2014-10-01 10:22:56
我想你可以在read_until(... timeout = timeout)上設置超時時間。 在源文件中,它基本上使用'find'作爲匹配,所以只是想知道read_until(「\ x00」)應該工作。 – Anzel 2014-10-01 10:25:33