TELNET 终端设计与实现 python实现 计算机网络课程设计

设计内容

参照 RFC854、RFC855 文档,设计一个 TELNET 终端程序。

telnet协议 详见 telnet协议详解

TELNET 终端设计与实现 python实现 计算机网络课程设计_第1张图片

代码

import selectors
import socket
import sys

__all__ = ["Telnet"]

DEBUGLEVEL = 0
TELNET_PORT = 23
# Telnet protocol characters (don't change)
IAC = bytes([255])
DONT = bytes([254])
DO = bytes([253])
WONT = bytes([252])
WILL = bytes([251])
theNULL = bytes([0])
SE = bytes([240])
SB = bytes([250])

# Telnet protocol options code (don't change)
ECHO = bytes([1])  # echo
NOOPT = bytes([0])

if hasattr(selectors, 'PollSelector'):
    _TelnetSelector = selectors.PollSelector
else:
    _TelnetSelector = selectors.SelectSelector


class Telnet:

    def __init__(self, host=None, port=0,
                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
        self.host = host
        self.port = port
        self.timeout = timeout
        self.sock = None
        self.rawq = b''
        self.irawq = 0
        self.cookedq = b''
        self.eof = 0
        self.iacseq = b''  # Buffer for IAC
        self.sb = 0  # flag for SB and SE
        self.sbdataq = b''
        self.option_callback = None
        if host is not None:
            self.open(host, port, timeout)

    def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):

        self.eof = 0
        if not port:
            port = TELNET_PORT
        self.host = host
        self.port = port
        self.timeout = timeout
        self.sock = socket.create_connection((host, port), timeout)

    def __del__(self):
        self.close()

    def close(self):
        sock = self.sock
        self.sock = None
        self.eof = True
        self.iacseq = b''
        self.sb = 0
        if sock:
            sock.close()

    def get_socket(self):

        return self.sock

    def fileno(self):
        return self.sock.fileno()

    def write(self, buffer):
        if IAC in buffer:
            buffer = buffer.replace(IAC, IAC + IAC)
        self.sock.sendall(buffer)

    def read_eager(self):
        self.process_rawq()
        while not self.cookedq and not self.eof and self.sock_avail():
            self.fill_rawq()
            self.process_rawq()
        return self.read_very_lazy()

    def read_very_lazy(self):
        buf = self.cookedq
        self.cookedq = b''
        if not buf and self.eof and not self.rawq:
            raise EOFError('telnet connection closed')
        return buf

    def process_rawq(self):
        buf = [b'', b'']
        try:
            while self.rawq:
                c = self.rawq_getchar()
                if not self.iacseq:
                    if c == theNULL:
                        continue
                    if c == b"\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 = b''

                elif len(self.iacseq) == 2:
                    cmd = self.iacseq[1:2]
                    self.iacseq = b''
                    opt = c
                    if cmd in (DO, DONT):


                        self.sock.sendall(IAC + WONT + opt)
                    elif cmd in (WILL, WONT):

                        self.sock.sendall(IAC + DONT + opt)
        except EOFError:  # raised by self.rawq_getchar()
            self.iacseq = b''  # Reset on EOF
            self.sb = 0
            pass
        self.cookedq = self.cookedq + buf[0]
        self.sbdataq = self.sbdataq + buf[1]

    def rawq_getchar(self):
        if not self.rawq:
            self.fill_rawq()
            if self.eof:
                raise EOFError
        c = self.rawq[self.irawq:self.irawq + 1]
        self.irawq = self.irawq + 1
        if self.irawq >= len(self.rawq):
            self.rawq = b''
            self.irawq = 0
        return c

    def fill_rawq(self):

        if self.irawq >= len(self.rawq):
            self.rawq = b''
            self.irawq = 0

        buf = self.sock.recv(50)
        # self.msg("recv %r", buf)
        self.eof = (not buf)
        self.rawq = self.rawq + buf

    def sock_avail(self):
        with _TelnetSelector() as selector:
            selector.register(self, selectors.EVENT_READ)
            return bool(selector.select(0))

    def mt_interact(self):
        import _thread
        _thread.start_new_thread(self.listener, ())
        while 1:
            line = sys.stdin.readline()
            if not line:
                break
            self.write(line.encode('ascii'))

    def listener(self):
        while 1:
            try:
                data = self.read_eager()
            except EOFError:
                print('*** Connection closed by remote host ***')
                return
            if data:
                sys.stdout.write(data.decode('ascii'))
            else:
                sys.stdout.flush()

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.close()


def test():
    host = '******' # 远程服务器centos的ip 远程服务器需要先安装telnet服务并且运行
    port = 23
    with Telnet() as tn:
        tn.open(host, port, timeout=0.5)
        tn.mt_interact()


if __name__ == '__main__':
    test()

你可能感兴趣的:(python)