ggntalk 2021-07-23 应用版
"""
ggntalk (曾经) 是 ggn_2015 闲的无聊开发的 python3 下的通讯工具
后来 ggn_2015 删去了大部分功能,剩下一个很智障的的基于 socket 的通讯库
import ggntalk 后,在命令行中输入 ggntalk.help() 显示帮助信息
力争打造简洁易懂的中文 __doc__ 文档
"""
import socket
import _thread
import time
import traceback
import json
AUTHOR = "GGN_2015"
VERSION = "2021-07-23"
NAMELIST = []
FUNCLIST = {}
def add_instruction(ins_name, ins_object):
"""
指令名: add_instruction
原型: add_instruction(ins_name, ins_object, ins_message)
功能: 在帮助列表中注册一个命令
"""
FUNCLIST[ins_name] = ins_object
NAMELIST.append(ins_name)
NAMELIST.sort()
add_instruction("add_instruction", add_instruction)
def help(ins_name = ""):
"""
指令名: help
原型: help(ins_name = "")
功能: ins_name = "" 时输出指令列表,否则输出某个指令对应的 __doc__ 信息。
"""
if ins_name == "":
print("ggntalk VERSION = %s, AUTHOR = %s, 所有命令如下:" % (VERSION, AUTHOR))
if len(NAMELIST) == 0:
print(" <Empty>")
else:
for x in NAMELIST:
print(" " + x)
print("")
else:
if FUNCLIST.get(ins_name) != None:
print(FUNCLIST[ins_name].__doc__)
else:
print("help: 未找到对应的指令")
add_instruction("help", help)
def client_send(server_ip, server_port, message, receive_len = 1048576):
"""
指令名: client_send
原型: client_send(server_ip, server_port, message, receive_len = 1048576)
功能: 客户端向服务器发送消息并接收服务器返回的信息
要求: server_port 必须是一个 0 ~ 65535 之间的整数, receive_len 的单位是字节
注: 默认采用 UTF-8 方式对发送的信息进行编码
"""
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((server_ip, server_port))
client_socket.send(message.encode("utf-8"))
re_message = client_socket.recv(receive_len)
client_socket.close()
return re_message.decode("utf-8")
except:
client_socket.close()
return traceback.format_exc()
add_instruction("client_send", client_send)
def start_new_thread(func_object, argu_list = ()):
"""
指令名: start_new_thread
原型: start_new_thread(func_object, argu_list = ())
功能: 启动一个新的线程以执行某个函数
"""
_thread.start_new_thread(func_object, argu_list)
add_instruction("start_new_thread", start_new_thread)
def feedback(message, connection_socket, addr, func_object):
"""
函数名: feedback
函数原型: feedback(message, connecttion_socket, addr, func_object)
功能:用于将信息反馈给客户端,建议采用多线程的方式调用
"""
re_message = func_object(message, addr)
connection_socket.send(re_message.encode("utf-8"))
connection_socket.close()
add_instruction("feedback", feedback)
def run_server(server_object):
"""
指令名: run_server
原型: run_server(server_object)
功能: 启动一个初始化后的服务器
注: server_object 是一个已经准备就绪的 server_object 对象
"""
while server_object.running:
print("服务器正在监听中 ip = %s port = %s ..." % (server_object.server_ip, server_object.server_port))
try:
connection_socket, addr = server_object.accept()
except Exception as ex:
print(" 服务器 " + str(ex))
else:
print(" 得到来自 " + str(addr) + " 的数据信息")
message = connection_socket.recv(server_object.receive_len).decode("utf-8")
_thread.start_new_thread(feedback, (message, connection_socket, addr, server_object.func_object))
print("服务器运行结束 ip = %s port = %s ..." % (server_object.server_ip, server_object.server_port))
class server_object(object):
"""
类型名: server_object
功能: 该类型用来描述一个服务器的运行过程
成员列表:
func_object 负责根据客户需求计算反馈信息,需要接收
receive_len 服务器接收单条消息的最大字节数,默认 1048576 Byte
running = True 表示正在运行(默认), = False 表示服务器停止
server_ip 服务器的广域网/局域网 ip 地址
server_port 服务器的运行端口,类型为整数
server_socket 服务端对象
"""
def __init__(self, server_ip, server_port, func_object, receive_len = 1048576):
"""
函数名: server_object.__init__
函数原型: __init__(self, func_object)
要求: func_object 是一个函数,接收一个字符串参数和 一个 addr 参数,返回一个字符串参数
"""
self.func_object = func_object
self.server_ip = server_ip
self.server_port = server_port
self.running = True
self.receive_len = receive_len
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind ((server_ip, server_port))
self.server_socket.listen(128)
self.server_socket.settimeout(10)
def start(self):
start_new_thread(run_server, (self, ))
def restart(self):
print(" 正在重启服务器 ...")
self.stop()
print(" 耐心等待 12 秒后服务器重启 ...")
time.sleep(12)
self.running = True
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind ((self.server_ip, self.server_port))
self.server_socket.listen(128)
self.server_socket.settimeout(10)
self.start()
def accept(self):
return self.server_socket.accept()
def stop(self):
print(" 正在停止服务器 ...")
self.running = False
add_instruction("server_object", server_object)
def test_server_function(message, addr):
"""
函数名: test_server_function
函数原型: test_server_function(message, addr)
功能: 为了测试服务器而设计的轻量级服务函数,功能为对 message 执行 eval 后以字符串返回
"""
try:
return str(eval(message))
except:
return traceback.format_exc()
add_instruction("test_server_function", test_server_function)
def run_server_by_config(server_object, config_filename = "config.json"):
"""
指令名: run_server_by_config
原型: run_server_by_config(server_object, config_filename = "config.json")
功能: 根据 config.json 中的数据决定服务器是否运行,以及运行的端口号
运行方式: 不建立新的线程
"""
server_object.start()
while True:
try:
with open(config_filename) as f:
config = json.load(f)
except Exception as ex:
print(traceback.format_exc())
server_object.stop()
return False
else:
changed = False
if config.get("server_ip") != None and server_object.server_ip != config["server_ip"]:
changed = True
print(" 服务器求改运行的 ip 为: " + config["server_ip"])
server_object.server_ip = config["server_ip"]
if config.get("server_port") != None and server_object.server_port != config["server_port"]:
changed = True
print(" 服务器修改运行的端口为: " +str(config["server_port"]))
server_object.server_port = config["server_port"]
if config.get("running") != None and not config["running"]:
server_object.stop()
print(" 根据 config.json 中的信号, 服务器停止运行")
return True
if changed:
server_object.restart()
time.sleep(5)
add_instruction("run_server_by_config", run_server_by_config)
def stop_server_by_config(config_filename = "config.json"):
"""
函数名: stop_server_by_config
函数原型: stop_server_by_config(config_filename = "config.json")
功能: 利用文件耦合关闭服务器
"""
try:
with open(config_filename) as f:
config = json.load(f)
except Exception as e:
print(traceback.format_exc())
else:
config["running"] = False
with open(config_filename, "w") as f:
json.dump(config, f, indent=4)
print("正在利用 config 文件停止服务器,请等待十四秒 ...")
time.sleep(14)
config["running"] = True
with open(config_filename, "w") as f:
json.dump(config, f, indent=4)
print(" 设置完成")
add_instruction("stop_server_by_config", stop_server_by_config)
if __name__ == "__main__":
print("ggntalk 加载成功, VERSION = %s, AUTHOR = %s" % (VERSION, AUTHOR))
server = server_object("127.0.0.1", 12345, test_server_function)
run_server_by_config(server)
ggntalk 2021-07-23 BETA 测试版
"""
ggntalk (曾经) 是 ggn_2015 闲的无聊开发的 python3 下的通讯工具
后来 ggn_2015 删去了大部分功能,剩下一个很智障的的基于 socket 的通讯库
import ggntalk 后,在命令行中输入 ggntalk.help() 显示帮助信息
力争打造简洁易懂的中文 __doc__ 文档
"""
import socket
import _thread
import time
import traceback
import json
AUTHOR = "GGN_2015"
VERSION = "2021-07-23 BETA"
NAMELIST = []
FUNCLIST = {}
def add_instruction(ins_name, ins_object):
"""
指令名: add_instruction
原型: add_instruction(ins_name, ins_object, ins_message)
功能: 在帮助列表中注册一个命令
"""
FUNCLIST[ins_name] = ins_object
NAMELIST.append(ins_name)
NAMELIST.sort()
add_instruction("add_instruction", add_instruction)
def help(ins_name = ""):
"""
指令名: help
原型: help(ins_name = "")
功能: ins_name = "" 时输出指令列表,否则输出某个指令对应的 __doc__ 信息。
"""
if ins_name == "":
print("ggntalk VERSION = %s, AUTHOR = %s, 所有命令如下:" % (VERSION, AUTHOR))
if len(NAMELIST) == 0:
print(" <Empty>")
else:
for x in NAMELIST:
print(" " + x)
print("")
else:
if FUNCLIST.get(ins_name) != None:
print(FUNCLIST[ins_name].__doc__)
else:
print("help: 未找到对应的指令")
add_instruction("help", help)
def client_send(server_ip, server_port, message, receive_len = 1048576):
"""
指令名: client_send
原型: client_send(server_ip, server_port, message, receive_len = 1048576)
功能: 客户端向服务器发送消息并接收服务器返回的信息
要求: server_port 必须是一个 0 ~ 65535 之间的整数, receive_len 的单位是字节
注: 默认采用 UTF-8 方式对发送的信息进行编码
"""
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((server_ip, server_port))
client_socket.send(message.encode("utf-8"))
re_message = client_socket.recv(receive_len)
client_socket.close()
return re_message.decode("utf-8")
except:
client_socket.close()
return traceback.format_exc()
add_instruction("client_send", client_send)
def start_new_thread(func_object, argu_list = ()):
"""
指令名: start_new_thread
原型: start_new_thread(func_object, argu_list = ())
功能: 启动一个新的线程以执行某个函数
"""
_thread.start_new_thread(func_object, argu_list)
add_instruction("start_new_thread", start_new_thread)
def run_server(server_object):
"""
指令名: run_server
原型: run_server(server_object)
功能: 启动一个初始化后的服务器
注: server_object 是一个已经准备就绪的 server_object 对象
"""
while server_object.running:
print("服务器正在监听中 ip = %s port = %s ..." % (server_object.server_ip, server_object.server_port))
try:
connection_socket, addr = server_object.accept()
except Exception as ex:
print(" 服务器 " + str(ex))
else:
print(" 得到来自 " + str(addr) + " 的数据信息")
message = connection_socket.recv(server_object.receive_len)
connection_socket.send(server_object.func_object(message, addr).encode("utf-8"))
connection_socket.close()
print("服务器运行结束 ip = %s port = %s ..." % (server_object.server_ip, server_object.server_port))
class server_object(object):
"""
类型名: server_object
功能: 该类型用来描述一个服务器的运行过程
成员列表:
func_object 负责根据客户需求计算反馈信息,需要接收
receive_len 服务器接收单条消息的最大字节数,默认 1048576 Byte
running = True 表示正在运行(默认), = False 表示服务器停止
server_ip 服务器的广域网/局域网 ip 地址
server_port 服务器的运行端口,类型为整数
server_socket 服务端对象
"""
def __init__(self, server_ip, server_port, func_object, receive_len = 1048576):
"""
函数名: server_object.__init__
函数原型: __init__(self, func_object)
要求: func_object 是一个函数,接收一个字符串参数和 一个 addr 参数,返回一个字符串参数
"""
self.func_object = func_object
self.server_ip = server_ip
self.server_port = server_port
self.running = True
self.receive_len = receive_len
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind ((server_ip, server_port))
self.server_socket.listen(128)
self.server_socket.settimeout(10)
def start(self):
start_new_thread(run_server, (self, ))
def restart(self):
print(" 正在重启服务器 ...")
self.stop()
print(" 耐心等待 12 秒后服务器重启 ...")
time.sleep(12)
self.running = True
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind ((self.server_ip, self.server_port))
self.server_socket.listen(128)
self.server_socket.settimeout(10)
self.start()
def accept(self):
return self.server_socket.accept()
def stop(self):
print(" 正在停止服务器 ...")
self.running = False
add_instruction("server_object", server_object)
def test_server_function(message, addr):
"""
函数名: test_server_function
函数原型: test_server_function(message, addr)
功能: 为了测试服务器而设计的轻量级服务函数,功能为对 message 执行 eval 后以字符串返回
"""
try:
return str(eval(message))
except:
return traceback.format_exc()
add_instruction("test_server_function", test_server_function)
def run_server_by_config(server_object, config_filename = "config.json"):
"""
指令名: run_server_by_config
原型: run_server_by_config(server_object, config_filename = "config.json")
功能: 根据 config.json 中的数据决定服务器是否运行,以及运行的端口号
运行方式: 不建立新的线程
"""
server_object.start()
while True:
try:
with open(config_filename) as f:
config = json.load(f)
except Exception as ex:
print(traceback.format_exc())
server_object.stop()
return False
else:
changed = False
if config.get("server_ip") != None and server_object.server_ip != config["server_ip"]:
changed = True
print(" 服务器求改运行的 ip 为: " + config["server_ip"])
server_object.server_ip = config["server_ip"]
if config.get("server_port") != None and server_object.server_port != config["server_port"]:
changed = True
print(" 服务器修改运行的端口为: " +str(config["server_port"]))
server_object.server_port = config["server_port"]
if config.get("running") != None and not config["running"]:
server_object.stop()
print(" 根据 config.json 中的信号, 服务器停止运行")
return True
if changed:
server_object.restart()
time.sleep(5)
add_instruction("run_server_by_config", run_server_by_config)
def stop_server_by_config(config_filename = "config.json"):
"""
函数名: stop_server_by_config
函数原型: stop_server_by_config(config_filename = "config.json")
功能: 利用文件耦合关闭服务器
"""
try:
with open(config_filename) as f:
config = json.load(f)
except Exception as e:
print(traceback.format_exc())
else:
config["running"] = False
with open(config_filename, "w") as f:
json.dump(config, f, indent=4)
print("正在利用 config 文件停止服务器,请等待十四秒 ...")
time.sleep(14)
config["running"] = True
with open(config_filename, "w") as f:
json.dump(config, f, indent=4)
print(" 设置完成")
add_instruction("stop_server_by_config", stop_server_by_config)
if __name__ == "__main__":
print("ggntalk 加载成功, VERSION = %s, AUTHOR = %s" % (VERSION, AUTHOR))
server = server_object("127.0.0.1", 12345, test_server_function)
run_server_by_config(server)