65.9K
CodeProject 正在变化。 阅读更多。
Home

一个简单的 Python Telnet 服务器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (5投票s)

2011年3月26日

GPL3

4分钟阅读

viewsIcon

55926

downloadIcon

1394

使用 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" 类型,则该函数必须有两个参数 (clientdata)。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_postset_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 版本。我知道它不完整,这个程序有一些已知的错误,并且需要更多的错误处理。但我认为它非常可用,至少在我的情况下是这样。
© . All rights reserved.