python 创建 Telnet 客户端

news2024/11/29 12:00:38

目录

前言

1. Telnet 客户端框架

2. Telnet 代码分解

2.1 基于 TK 创建会话窗口

2.1.1 创建 Text 文本控件

2.1.2 创建 Frame 容器

2.1.2.1 基于 Frame 容器创建主机地址输入框

2.1.2.1.1 主机地址输入框绑定焦点事件

2.1.2.2 创建 Telnet 连接按钮控件

2.1.2.3 创建 Telnet 断开按钮控件

2.1.2.4 基于 Frame 容器创建发送命令输入框

2.1.2.4.1 发送命令输入框绑定焦点事件

2.1.2.5 创建执行命令按钮控件

2.2 Telnet 连接与断开服务器过程

2.2.1 Telnet 连接服务器

2.2.2 Telnet 断开服务器 

2.3 Telnet 会话交互过程

2.3.1 Telnet 客户端向服务器发送命令

2.3.2 Telnet 客户端接收服务器返回的数据 

3. Telnet 客户端代码总览 

4. Telnet 客户端效果展示 

5. 总结


前言

最近由于某些特殊项目的需要,匆忙通过 python 实现了一个简易版的 Telnet 客户端。这个客户端目前来说是有缺陷的(比如,不能 vi 读写文件内容,不能执行阻塞型命令 ping 等),但是感觉比较好玩,所以想与大家分享一下。

1. Telnet 客户端框架

2. Telnet 代码分解

接下来,我们就基于 Telnet客户端框架 来逐步拆分讲解代码构成。

2.1 基于 TK 创建会话窗口

# 创建窗口并设置标题
window = tk.Tk()
window.title("Telnet客户端")

# 设置tk.Tk窗口的背景颜色为浅蓝色
window.config(bg="sky blue")

2.1.1 创建 Text 文本控件

# 创建一个Text文本控件
console_text = tk.Text(window, width=200, height=70, bg="black", fg="white")
console_text.pack(pady=5)

# 定义一个字体样式
console_text.tag_configure("bold_tag", font=("Arial", 11))

2.1.2 创建 Frame 容器

# 创建一个Frame用于放置输入框和按钮,并设置Frame在下方空开5个空格
frame = tk.Frame(window, bg="sky blue")
frame.pack(pady=5)

2.1.2.1 基于 Frame 容器创建主机地址输入框

# 创建一个输入框控件,并放置在Frame中,同时设置右侧空开3个空格
host_addr_entry = tk.Entry(frame, width=50, font=("Arial", 12, "bold"))
host_addr_entry.insert(0, "请输入主机地址...")
host_addr_entry.config(fg="gray")
host_addr_entry.pack(side=tk.LEFT, padx=3)
2.1.2.1.1 主机地址输入框绑定焦点事件
# 绑定获取焦点和失去焦点事件,显示和隐藏提示语
host_addr_entry.bind("<FocusIn>", on_host_entry_focus_in)
host_addr_entry.bind("<FocusOut>", on_host_entry_focus_out)

# 获取焦点事件
def on_host_entry_focus_in(event):
    if host_addr_entry.get() == "请输入主机地址...":
        host_addr_entry.delete(0, tk.END)
        host_addr_entry.config(fg="black")

# 失去焦点事件
def on_host_entry_focus_out(event):
    if host_addr_entry.get() == "":
        host_addr_entry.insert(0, "请输入主机地址...")
        host_addr_entry.config(fg="gray")

2.1.2.2 创建 Telnet 连接按钮控件

# 创建一个按钮控件,并放置在Frame中
connect_button = tk.Button(frame, text="连接 Telnet", font=("Arial", 12, "bold"), fg="white", bg="#46C0FB", command=connect_telnet)
connect_button.pack(side=tk.LEFT, padx=3)

2.1.2.3 创建 Telnet 断开按钮控件

# 创建断开按钮控件,并放置在Frame中,右侧空开3个空格
disconnect_button = tk.Button(frame, text="断开 Telnet", font=("Arial", 12, "bold"), fg="white", bg="#46C0FB", command=disconnect_telnet, state=tk.DISABLED)
disconnect_button.pack(side=tk.LEFT, padx=3)

2.1.2.4 基于 Frame 容器创建发送命令输入框

# 创建一个输入框控件,并放置在Frame中,同时设置右侧空开3个空格
command_entry = tk.Entry(frame, width=50, font=("Arial", 12, "bold"))
command_entry.insert(0, "请发送指令...")
command_entry.config(fg="gray")
command_entry.pack(side=tk.LEFT, padx=12)
2.1.2.4.1 发送命令输入框绑定焦点事件
# 绑定获取焦点和失去焦点事件,显示和隐藏提示语
command_entry.bind("<FocusIn>", on_entry_focus_in)
command_entry.bind("<FocusOut>", on_entry_focus_out)

# 获取焦点事件
def on_entry_focus_in(event):
    if command_entry.get() == "请发送指令...":
        command_entry.delete(0, tk.END)
        command_entry.config(fg="black")

# 失去焦点事件
def on_entry_focus_out(event):
    if command_entry.get() == "":
        command_entry.insert(0, "请发送指令...")
        command_entry.config(fg="gray")

2.1.2.5 创建执行命令按钮控件

# 创建执行按钮控件,并放置在Frame中,右侧空开3个空格
execute_button = tk.Button(frame, text="执行命令", font=("Arial", 12, "bold"), fg="white", bg="#46C0FB", command=execute_command, state=tk.DISABLED)
execute_button.pack(side=tk.LEFT)

2.2 Telnet 连接与断开服务器过程

2.2.1 Telnet 连接服务器

def connect_telnet():
    host = host_addr_entry.get() # 获取输入框内的主机地址
    port = 23            # 默认telnet端口
    username = 'root'    # 登录用户名
    password = '123456'  # 登录密码

    try:
        # 连接Telnet服务器
        telnet_client = telnetlib.Telnet(host, port, timeout=5)
        console_text.insert(tk.END, "成功连接到Telnet服务器。\n", "bold_tag")
        connect_button.config(state=tk.DISABLED)
        disconnect_button.config(state=tk.NORMAL)
        execute_button.config(state=tk.NORMAL)

        # 输入登录用户名
        telnet_client.read_until(b'login:')
        telnet_client.write(username.encode('ascii') + b"\n")

        # 输入登录密码
        telnet_client.read_until(b'Password:')
        telnet_client.write(password.encode('ascii') + b"\n")
        print('成功登录到设备:' + host)

        # 启动后台信息接收线程
        receive_thread = threading.Thread(target=receive_background_info)
        receive_thread.start()

    except Exception as e:
        console_text.insert(tk.END, f"连接失败: {e}\n", "bold_tag")

2.2.2 Telnet 断开服务器 

def disconnect_telnet():
    if telnet_client:
        telnet_client.close()
        console_text.insert(tk.END, "已断开Telnet连接。\n", "bold_tag")
        connect_button.config(state=tk.NORMAL)
        disconnect_button.config(state=tk.DISABLED)
        execute_button.config(state=tk.DISABLED)

2.3 Telnet 会话交互过程

2.3.1 Telnet 客户端向服务器发送命令

def execute_command():
    command = command_entry.get() + "\n"
    telnet_client.write(command.encode('ascii'))
    command_entry.delete(0, tk.END)

2.3.2 Telnet 客户端接收服务器返回的数据 

def receive_background_info():
    while True:
        try:
            output_data = telnet_client.read_very_eager().decode('utf-8')
            if output_data:
                clean_color_data = remove_color_codes(output_data.strip())
                console_text.insert(tk.END, clean_color_data, "bold_tag")
                time.sleep(0.5)
            except EOFError:
                break
            except Exception as e:
                console_text.insert(tk.END, f"错误: {e}\n", "bold_tag")
                break

    def remove_color_codes(data):
        # 使用正则表达式匹配ANSI转义码,并替换为空字符串
        ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
        return ansi_escape.sub('', data)

3. Telnet 客户端代码总览 

import tkinter as tk
import telnetlib
import threading
import time
import re

class TeneltTool:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Telnet客户端")
        # 设置tk.Tk窗口的背景颜色为浅蓝色
        self.window.config(bg="sky blue")

        # 创建一个200x70的Text文本控件,并且设置背景为黑色
        self.console_text = tk.Text(self.window, width=200, height=70, bg="black", fg="white")
        self.console_text.pack(pady=5)
        # 定义一个字体样式
        self.console_text.tag_configure("bold_tag", font=("Arial", 11))

        # 创建一个Frame用于放置输入框和按钮,并设置Frame在下方空开5个空格
        frame = tk.Frame(self.window, bg="sky blue")
        frame.pack(pady=5)

        # 创建一个输入框控件,并放置在Frame中,同时设置右侧空开3个空格
        self.host_addr_entry = tk.Entry(frame, width=50, font=("Arial", 12, "bold"))
        self.host_addr_entry.insert(0, "请输入主机地址...")
        self.host_addr_entry.config(fg="gray")
        self.host_addr_entry.pack(side=tk.LEFT, padx=3)

        # 创建一个按钮控件,并放置在Frame中
        self.connect_button = tk.Button(frame, text="连接 Telnet", font=("Arial", 12, "bold"), fg="white", bg="#46C0FB",
                                        command=self.connect_telnet)
        self.connect_button.pack(side=tk.LEFT, padx=3)

        # 创建断开按钮控件,并放置在Frame中,右侧空开3个空格
        self.disconnect_button = tk.Button(frame, text="断开 Telnet", font=("Arial", 12, "bold"), fg="white",
                                           bg="#46C0FB", command=self.disconnect_telnet, state=tk.DISABLED)
        self.disconnect_button.pack(side=tk.LEFT, padx=3)

        # 绑定获取焦点和失去焦点事件,显示和隐藏提示语
        self.host_addr_entry.bind("<FocusIn>", self.on_host_entry_focus_in)
        self.host_addr_entry.bind("<FocusOut>", self.on_host_entry_focus_out)

        # 创建一个输入框控件,并放置在Frame中,同时设置右侧空开3个空格
        self.command_entry = tk.Entry(frame, width=50, font=("Arial", 12, "bold"))
        self.command_entry.insert(0, "请发送指令...")
        self.command_entry.config(fg="gray")
        self.command_entry.pack(side=tk.LEFT, padx=12)

        # 绑定获取焦点和失去焦点事件,显示和隐藏提示语
        self.command_entry.bind("<FocusIn>", self.on_entry_focus_in)
        self.command_entry.bind("<FocusOut>", self.on_entry_focus_out)

        # 创建执行按钮控件,并放置在Frame中,右侧空开3个空格
        self.execute_button = tk.Button(frame, text="执行命令", font=("Arial", 12, "bold"), fg="white",
                                        bg="#46C0FB", command=self.execute_command, state=tk.DISABLED)
        self.execute_button.pack(side=tk.LEFT)

        self.telnet_client = None
        self.receive_thread = None

    def on_host_entry_focus_in(self, event):
        if self.host_addr_entry.get() == "请输入主机地址...":
            self.host_addr_entry.delete(0, tk.END)
            self.host_addr_entry.config(fg="black")

    def on_host_entry_focus_out(self, event):
        if self.host_addr_entry.get() == "":
            self.host_addr_entry.insert(0, "请输入主机地址...")
            self.host_addr_entry.config(fg="gray")

    def on_entry_focus_in(self, event):
        if self.command_entry.get() == "请发送指令...":
            self.command_entry.delete(0, tk.END)
            self.command_entry.config(fg="black")

    def on_entry_focus_out(self, event):
        if self.command_entry.get() == "":
            self.command_entry.insert(0, "请发送指令...")
            self.command_entry.config(fg="gray")

    def connect_telnet(self):
        host = self.host_addr_entry.get() # 获取输入框内的主机地址
        port = 23             # 默认telnet端口
        username = 'root'     # 登录用户名
        password = '123456'   # 登录密码

        try:
            # 连接Telnet服务器
            self.telnet_client = telnetlib.Telnet(host, port, timeout=5)
            self.console_text.insert(tk.END, "成功连接到Telnet服务器。\n", "bold_tag")
            self.connect_button.config(state=tk.DISABLED)
            self.disconnect_button.config(state=tk.NORMAL)
            self.execute_button.config(state=tk.NORMAL)
            # 输入登录用户名
            self.telnet_client.read_until(b'login:')
            self.telnet_client.write(username.encode('ascii') + b"\n")
            # 输入登录密码
            self.telnet_client.read_until(b'Password:')
            self.telnet_client.write(password.encode('ascii') + b"\n")
            print('成功登录到设备:' + host)

            # 启动后台信息接收线程
            self.receive_thread = threading.Thread(target=self.receive_background_info)
            self.receive_thread.start()

        except Exception as e:
            self.console_text.insert(tk.END, f"连接失败: {e}\n", "bold_tag")

    def disconnect_telnet(self):
        if self.telnet_client:
            self.telnet_client.close()
            self.console_text.insert(tk.END, "已断开Telnet连接。\n", "bold_tag")
            self.connect_button.config(state=tk.NORMAL)
            self.disconnect_button.config(state=tk.DISABLED)
            self.execute_button.config(state=tk.DISABLED)

    def execute_command(self):
        command = self.command_entry.get() + "\n"
        self.telnet_client.write(command.encode('ascii'))
        self.command_entry.delete(0, tk.END)

    def receive_background_info(self):
        while True:
            try:
                output_data = self.telnet_client.read_very_eager().decode('utf-8')
                if output_data:
                    clean_color_data = self.remove_color_codes(output_data.strip())
                    self.console_text.insert(tk.END, clean_color_data, "bold_tag")
                    # self.console_text.see(tk.END)
                time.sleep(0.5)
            except EOFError:
                break
            except Exception as e:
                self.console_text.insert(tk.END, f"错误: {e}\n", "bold_tag")
                break

    def remove_color_codes(self, data):
        # 使用正则表达式匹配ANSI转义码,并替换为空字符串
        ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
        return ansi_escape.sub('', data)

if __name__ == "__main__":
    tenelt_tool = TeneltTool()
    tenelt_tool.window.mainloop()

4. Telnet 客户端效果展示 

5. 总结

由于这个工具是匆忙之间创作的,所以还存在一些缺陷,大家如果感兴趣,就拷贝源码自行优化吧。 

好啦,本章内容到此结束,感谢大家的热爱与支持~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/987007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习——图片处理应用(人脸补全)

0、前言&#xff1a;本文内容是机器学习算法回归预测的应用&#xff0c;其中数据集主要来自sklearn库自带的人脸数据&#xff0c;目的是通过KNN回归、线性回归、岭回归算法通过人物的左半张脸预测人物的右半张脸。 意义1&#xff1a;通过该项目掌握图片数据在机器学习当中的处…

CSS笔记(黑马程序员pink老师前端)圆角边框

圆角边框 border-radius:length; 效果显示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Documen…

【新项目】

01 概述 新凝血四项&#xff0c;又称血栓前四项&#xff0c;分为&#xff1a;TAT、PIC、TM、tPAI.C四个检测项目。 生理性高凝状态会伴随着孕妈妈们的整个妊娠期&#xff0c;凝血和纤溶系统的异常状态导致孕产妇发生静脉血栓栓塞症(VTE)的风险比一般人群高。非妊娠妇女凝血项…

LeetCode518. 零钱兑换 II

518. 零钱兑换 II 一、题目 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证…

RTMP流媒体服务器EasyDSS视频直播点播平台如何生成可自动播放的分享链接

EasyDSS支持一站式的上传、转码、直播、回放、嵌入、分享功能&#xff0c;具有多屏播放、自由组合、接口丰富等特点。平台可以为用户提供专业、稳定的直播推流、转码、分发和播放服务&#xff0c;全面满足超低延迟、超高画质、超大并发访问量的要求。在推流方面&#xff0c;Eas…

PostgreSQL PG15 新功能 PG_WALINSPECT

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis &#xff0c;Oracle ,Oceanbase 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请加微信号 liuaustin3 &#xff08;…

ABAP内表排序

SORT在用于给内表排序时&#xff0c;后面可以用ASCENDING和DESCENDING进行升序和降序排列&#xff0c;但是这其中用法很多&#xff0c;经过尝试后总结如下&#xff1a; 1.SORT LT_TAB BY WERKS LGORT EMAIL. 正常排序并使用默认ASCENDING. 2.SORT LT_TAB BY WERKS LGORT EMAI…

Java测试(10)--- selenium

1.定位一组元素 &#xff08;1&#xff09;如何打开本地的HTML页面 拼成一个URL &#xff1a;file: /// 文件的绝对路径 import os os.path.abspath(文件的绝对路径&#xff09; &#xff08;2&#xff09;先定位出同一类元素&#xff08;tag name&#xff0c;name&…

NUC980webServer开发

目录 1.RTL8189FTV驱动移植 2.wifi配置工具hostapd移植 1.openssl-1.0.2r交叉编译 2.libnl-3.2.25.tar.gz交叉编译 3.hostapd-2.9.tar.gz交叉编译 4.移植相关工具到开发板 1.RTL8189FTV驱动移植 1. 把驱动文件源码放在linux源码的drivers/net/wireless/realtek/rtlwifi/目录…

LeetCode //C - 114. Flatten Binary Tree to Linked List

114. Flatten Binary Tree to Linked List Given the root of a binary tree, flatten the tree into a “linked list”: The “linked list” should use the same TreeNode class where the right child pointer points to the next node in the list and the left child …

在Android和iOS上设置手机ip详细教程

大家好&#xff01;今天我们将分享一个关于如何在Android和iOS设备上设置手机ip&#xff08;Layer 2 Tunneling Protocol&#xff09;的简易教程。如果你想要通过安全且可靠的方式连接到远程网络&#xff0c;那么跟着本文一起学习吧&#xff01;无需复杂操作&#xff0c;让我们…

KUKA机器人后台控制程序(SPS)介绍

KUKA机器人后台控制程序(SPS)介绍 KUKA机器人后台控制程序主要包括以下几部分: RC:运动控制、机器人轨迹规划 优先级1 I/O刷新:输入输出信号的控制 优先级1 SPS:用户可编辑的后台逻辑程序 优先级2 显示界面刷新:示教器显示画面的控制 优先级3 以上的程序需要12ms(固定…

企业架构LNMP学习笔记19

Nginx 第三方模块的使用&#xff1a; Nginx官方没有的功能&#xff0c;开源开发人员定制开发了一些功能&#xff0c;把代码公布出来&#xff0c;可以通过编译加载第三方模块的方式&#xff0c;使用新功能。 NGINX 3rd Party Modules | NGINX shell > tar xvf ngx-fancyinde…

CVE-2017-12149

春秋云镜 CVE-2017-12149 JBoss反序列化漏洞 靶标介绍 2017年8月30日&#xff0c;厂商Redhat发布了一个JBOSSAS 5.x 的反序列化远程代码执行漏洞通告。该漏洞位于JBoss的HttpInvoker组件中的 ReadOnlyAccessFilter 过滤器中&#xff0c;其doFilter方法在没有进行任何安全检查…

Win10怎么设置待机时间

我们在使用电脑的过程中&#xff0c;经常因为有事需要离开电脑&#xff0c;长时间不操作电脑就会进行待机睡眠状态&#xff0c;那么Win10怎么设置待机时间呢&#xff0c;下面小编就给大家详细介绍一下Win10设置待机时间的方法&#xff0c;大家感兴趣的话可以来看一看。 设置方…

新华社《中国扫描十年发展图鉴》:扫描全能王为3亿用户带去“掌心里的便利”

扫描设备从“两手搬”到“进口袋”的过程中经历了什么&#xff1f; 近日&#xff0c;新华社发布了《中国扫描十年发展图鉴》&#xff08;简称《图鉴》&#xff09;&#xff0c;对扫描设备、技术、应用领域的发展历史进行了深入盘点。《图鉴》显示&#xff0c;扫描一度是价格接…

MySQL——数据的删除以及MySQL中的约束

删除数据 删除表中的一行数据&#xff0c;也必须加上 WHERE条件&#xff0c;否则整列的数据都会被删除。删除语句&#xff1a; delete from 表名 where 条件; 他会将所有的符合条件的数据删除&#xff0c;如果不写条件&#xff0c;则表中的数据全部删除&#xff1a; 如果不添…

软件测试/测试开发丨学会与 AI 对话,高效提升学习效率

点此获取更多相关资料 简介 ChatGPT 的主要优点之一是它能够理解和响应自然语言输入。在日常生活中&#xff0c;沟通本来就是很重要的一门课程&#xff0c;沟通的过程中表达越清晰&#xff0c;给到的信息越多&#xff0c;那么沟通就越顺畅。 和 ChatGPT 沟通也是同样的道理&…

方向介绍:基于深度学习的轨迹预测

方向介绍&#xff1a;基于深度学习的轨迹预测 文章目录 方向介绍&#xff1a;基于深度学习的轨迹预测问题定义典型方法挑战未来展望参考 基于深度学习的轨迹预测是一种利用神经网络模型来预测移动物体的未来位置和运动状态的技术。这种技术在许多领域都有重要的应用&#xff0c…

Jetpack Compose 入门教程之Text

这个文本显示组件应该是我们最常用的组件,下面会非常细 归纳 实例 下面一一演示这些属性与控制逻辑 文本的展示 Text组件 所有构造方法都是text:String,要想用string.xml里面的字符串资源 得使用 stringResource方法,其相似方法如下/** Copyright 2019 The Android Open Sou…