一个简单的 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 版本。我知道它不完整,这个程序有一些已知的错误,并且需要更多的错误处理。但我认为它非常可用,至少在我的情况下是这样。