2014-10-01 3 views
1

메시지와 함께 나에게 응답하고 각 메시지 끝에는 읽을 수없는 16 진수 (null 문자)가 추가됩니다.파이썬이 텔넷에서 null 문자까지 읽음

: STH 등을해야하는 반면

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

:이 출력을 반환

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

: 나는 간단한 예를 통해 통해 검색을 시도했지만 작동 할 수없는 것

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

문자열 문자의 끝을 얻을 수있는 방법이 있습니까? 문자가 의도적으로 누락 된 경우 바이트를 출력으로 가져올 수 있습니까?

00 문자

이있다 : 나는 < (50)의 명성이 있기 때문에 내가 코멘트를 추가 할 수 없습니다

tcpdump

답변

1

나는이 같은 문제의 발견 - telnetlib 메시지에서 모든 × 00을 억제하는 것입니다. 프레드릭 요한슨 (Fredrik Johansson)은 잘 대답 했으므로 telnetlib가 구현 된 방식입니다.

하나 개의 솔루션은 모든 null 문자를 먹지 않는 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 

다음 텔넷 클래스를 오버라이드 (override) '을 방법 :

telnetlib.Telnet.process_rawq = _process_rawq 

이 나를 위해 문제를 해결했다.

0

. read_until("") 또는 read_all()을 사용해 보셨습니까? 이 경우 누락 된 문자를 캡처 할 수 있습니까?

+0

나는 그들을 시험해 보았지만 해결책이 아닙니다. 내가 그들을 사용할 때, 나는 타임 아웃을 설정해야만했으며,이 경우 타임 아웃을 기다릴 때마다 기다렸다가 많은 양의 데이터를 보낼 때 충분히 효율적이지 못했다. 그리고 그 시간 초과 후에 응답을 포착하지 못할 수도 있습니다. timeout을 설정하지 않으면 알 수없는 시간 동안 연결이 차단됩니다. – brian

+0

나는 당신이 read_until (... timeout = timeout)에서 시간 제한을 설정할 수 있다고 생각한다. 원본 파일에 을 사용하면 기본적으로 일치하는 항목에 대해 '찾기'가 사용되므로 read_until ("\ x00")이 작동해야합니다. – Anzel

1

이 코드 (http://www.opensource.apple.com/source/python/python-3/python/Lib/telnetlib.py)는 null 문자를 무시한 것 같습니다. 그게 정말로 올바른 행동입니까?

예를 들어 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를 사용하여 설정되고 네트워크 가상 터미널 (NVT)을 기반으로합니다. 클라이언트에서 Telnet 프로그램은 들어오는 NVT 코드를 클라이언트의 디스플레이 장치 인 이 이해할 수있는 코드로 변환하고 클라이언트가 생성 한 키보드 코드를 발신 NVT 코드로 변환하는 역할을 담당하는 입니다.

NVT는 문자에 7 비트 코드를 사용합니다. RFC에서 프린터로 이라고 표시된 디스플레이 장치는 표준 을 표시하고 7 비트 코드로 표시되는 ASCII 문자를 표시하고 을 인식하고 특정 제어 코드를 처리하기 만하면됩니다. 7 비트 문자는 최대 비트가 0으로 설정된 8 비트 바이트로 전송 된 입니다. 줄 끝은 캐리지 리턴 (CR) 다음에 줄 바꿈 (LF)으로 전송됩니다. 실제 캐리지 리턴을 전송하려는 경우 이것은 캐리지 리턴으로 전송 된 후 NUL (모든 비트는 제로) 문자로 전송됩니다.텔넷을 사용하여 RS232-TCP/IP 변환기에서 데이터를 얻을하려고 할 때

Name  Code Decimal Value 
Function NULL NUL 0 No operation