一个简单的 Python Telnet 服务器
使用 Python 编写的一个简单的 Telnet 服务器
引言
这个服务器使用 Telnet 协议,尽管现在 HTTP 已经取代了它,但 Telnet 仍然非常简单轻量。它不需要一个沉重的服务器或复杂的动态函数编写方法。几乎所有要发送的内容都基于文本。我运行一个 Windows 服务器,并且制作了这个程序来维护 Windows 服务器。这个程序可以用作一个简单的监控程序。您可以通过 Telnet 检查您的服务器是否正常。您需要做的只是添加一个脚本或修改一些 Python 代码。
背景
此服务器使用 Telnet 协议、ANSI 代码和 ZModem 编写。这些在当今并不常见。所以,如果您熟悉这个协议,您可以根据自己的目的进行修改。如果您了解 Python 语言,您可以轻松理解代码。
使用服务器
1. 编写脚本
该服务器使用脚本添加用户功能。脚本由两部分组成。一个是文本,另一个是动作宏。服务器将文本原封不动地发送给客户端,但动作宏不会。服务器解析以 "{%" 开头并以 "%}" 结尾的动作宏。在这些分隔符之间,服务器解析字符串并提取函数名称和类型。如果字符串以 "ansi" 开头,则表示服务器将调用 STANSICode 中的函数。如果字符串以 "set" 开头,则表示服务器将从客户端获取一些数据。如果字符串以 "get" 开头,则表示服务器将调用该函数并获取返回值,该值将被发送到客户端。
{%
ansi:Move(12,14);
set:STLoginID;
set:STLoginPassword;
%}
2. 编写用户函数
解析脚本后,服务器将调用 STUserHandler 中的用户函数。如果用户函数是 "set" 类型,则该函数必须有两个参数 (client 和 data)。client 是客户端对象,用于了解哪个客户端调用了此函数。data 是来自客户端的数据。
def STLoginID(client, data):
    data = getAlphabetNumber(data)
    if data:
        client.user_id = data
        client.send(STANSICode().Move(12, 15))
        client.sendDirectly(getIACCommand('WILL','ECHO'))
        return ""
    else:
        return "repeat"
    if client != None:
        return "root"
    return "repeat"
根据函数的返回值,客户端处理程序的行为有所不同。如果用户函数返回 "repeat",则处理程序不会更改脚本。它保留脚本的状态并仅处理来自客户端的数据。我将在下面列出各种类型
| 返回类型 | 操作 | 
| 脚本关键词 | 转到包含 "KEYWORD" 的脚本 | 
| 刷新 | 清除屏幕并转到相同的脚本 | 
| 保持 | 保留脚本,不清除屏幕 | 
| 重复 | 什么都不做,只接收数据 | 
| 根 | 转到根脚本 | 
3. 客户端信息
当服务器接受客户端时,服务器会创建每个客户端对象。每个客户端都有这些私有数据:用户 ID、昵称、密码等等... page_index 表示列表中当前的页面索引。keyword 表示当前要在屏幕上显示的脚本。set_commands 是一个包含将要被调用的函数列表的向量。set_post 与 set_commands 相同,但时序不同。
class STClient():
    def __init__(self):
        self.user_id = 'GUEST'
        self.nick_name = 'GUEST'
        self.password = ''
        self.keyword = 'root'
        self.set_commands = []
        self.set_post = []
        self.status = "none"
        self.zmodem = None
        self.page_index = 0
        self.client_data = [] # this list for an user
        self.command = None
        client_list.append(self)
...
4. 类描述
这是对关键类的简短说明
| 类名 | 规则 | 
| STClientHandler | 使用脚本处理客户端 | 
| STClientSocket | 这是一个客户端套接字,用于与客户端对象对应。此类是使用 ( server = ThreadingTCPServer) 创建的。当创建客户端套接字时,线程也会被创建。因此,每个客户端套接字都有一个线程来发送和接收数据。 | 
| STDatabase | 通过 SQLite3 处理成员账户,创建表,更新成员状态。 | 
| STSettings | 编写默认设置值 | 
其他有用的类
简单的 Telnet 服务器有一些附加功能,ZModem 和一个命令 Shell。ZModem 用于从客户端上传和下载文件。我制作了这个模块,参考了这份文档:http://www.ifremer.fr/lpo/gliders/donnees_tt/tech/protocoles/readme_zmodem_doc.pdf。
1. ZModem
download = ZModem.zmodem(client) # Create Zmodem instance
download.send_files(filelist) # send files in filelist to the client
upload = ZModem.zmodem(client) # Create Zmodem instance
upload.receive_files(telnet_pds_path) # get and save the file to telnet_pds_path
2. 命令 Shell
这是用于 Python 的 DOS 命令 Shell。我使用 pywin32 创建一个进程和一个管道。Python 的 popen 在从管道读取数据时存在阻塞问题。我修改了这个基本代码,来源于 pywin32 演示代码 runproc.py。您可以将此模块用作独立的批处理工具。
command = Command() # create Cmd instance
command.run() # run thread and "cmd.exe" process
command.sendCommand("exit") # send command to cmd.exe through pipe and telnet
command.getResult()# get text after executing the command
command.end() # finish the thread
3. 更多功能
此服务器支持简单的登录、管理员脚本和一个非常非常简单的聊天模块。并且在提示符下,它可以直接向用户发送消息。
历史
- 0.1:这仍然是 Beta 版本。我知道它不完整,这个程序有一些已知的错误,并且需要更多的错误处理。但我认为它非常可用,至少在我的情况下是这样。




