174 lines
6.7 KiB
Python
174 lines
6.7 KiB
Python
import ctypes
|
||
import asyncio
|
||
import websockets
|
||
import hashlib
|
||
import time
|
||
import json
|
||
|
||
# 加载DLL文件
|
||
sainiu_api = ctypes.CDLL('SaiNiuApi.dll')
|
||
|
||
# 定义函数参数类型和返回值类型
|
||
sainiu_api.Access_ServerStart.argtypes = [
|
||
ctypes.c_int,
|
||
ctypes.c_bool,
|
||
ctypes.c_bool,
|
||
ctypes.c_bool,
|
||
ctypes.c_bool,
|
||
ctypes.c_int,
|
||
ctypes.c_char_p,
|
||
ctypes.c_bool,
|
||
ctypes.c_bool
|
||
]
|
||
sainiu_api.Access_ServerStart.restype = ctypes.c_char_p # 返回值类型为文本型(字符串)
|
||
|
||
# 调用函数时传入的参数
|
||
port = 3030 # WS以及HTTP的请求端口,默认3030
|
||
web_socket = True # 是否开启WebSocket
|
||
http_server = True # 是否开启HTTP请求
|
||
remote = False # 是否开启远程请求
|
||
log = True # 是否开启日志功能
|
||
ws_max = 0 # 设置WS客户端最大连接数,0 = 不限制
|
||
sign_key = b'111111' # 签名key,留空表示无需签名请求 调试时建议修改为空
|
||
sha256 = True # sign签名方式,假 = md5,真 = hmac - sha256
|
||
version_tip = True # 是否开启SDK版本与DLL不一致时的刷新提示
|
||
|
||
# 启动服务器
|
||
result = sainiu_api.Access_ServerStart(
|
||
port,
|
||
web_socket,
|
||
http_server,
|
||
remote,
|
||
log,
|
||
ws_max,
|
||
sign_key,
|
||
sha256,
|
||
version_tip
|
||
)
|
||
|
||
print(f"Access_ServerStart 服务器启动: {result.decode('gbk')}")
|
||
|
||
# 计算sign值
|
||
def sign_GetSign(signKey, post, time, sha256=False):
|
||
# 拼接字符串
|
||
data = post + str(time) + signKey
|
||
|
||
# 将字符串转换为字节集
|
||
byte_data = data.encode('utf-8')
|
||
|
||
# 根据sha256参数选择哈希算法
|
||
if sha256:
|
||
hash_object = hashlib.sha256(byte_data)
|
||
else:
|
||
hash_object = hashlib.md5(byte_data)
|
||
|
||
# 获取十六进制表示并转换为小写
|
||
sign = hash_object.hexdigest().lower()
|
||
|
||
return sign
|
||
|
||
async def connect_to_websocket():
|
||
while True:
|
||
try:
|
||
# 获取当前的13位时间戳(毫秒级)
|
||
current_time_ws = int(time.time() * 1000)
|
||
|
||
# 计算签名,参数post参数为"ws"不可修改,signKey为自定义密匙,sha256参数为True选择sha256算法,为False则选择md5算法,需要与Access_StartServer的参数一致
|
||
ws_sign = sign_GetSign(sign_key.decode('utf-8'), "ws", current_time_ws, sha256)
|
||
|
||
# 构建URI
|
||
uri = f"ws://127.0.0.1:{port}?time={current_time_ws}&sign={ws_sign}"
|
||
|
||
async with websockets.connect(uri) as websocket:
|
||
print("已连接到ws服务器")
|
||
|
||
# 再次获取当前的13位时间戳(毫秒级)以避免签名超时
|
||
current_time_json = int(time.time() * 1000)
|
||
|
||
# 计算JSON数据的签名,参数post参数为"init"
|
||
json_sign = sign_GetSign(sign_key.decode('utf-8'), "Init", current_time_json, sha256)
|
||
|
||
# 发送JSON数据
|
||
message = {
|
||
"type": "Invoke_SaiNiu",
|
||
"traceId": "Access_Init",
|
||
"codeType": "Access",
|
||
"post": "Init",
|
||
"data": {
|
||
"AccessType": 0,
|
||
"AccessId": "AccessId", #替换成授权的AccessId,
|
||
"AccessKey": "AccessKey", #替换成授权的AccessKey
|
||
"ForceLogin": True
|
||
},
|
||
"time": current_time_json,
|
||
"sign": json_sign
|
||
}
|
||
|
||
await websocket.send(json.dumps(message))
|
||
print(f"Sent message: {message}")
|
||
|
||
try:
|
||
while True:
|
||
# 接收来自服务器的消息
|
||
response = await websocket.recv()
|
||
print(f"接收来自服务器的消息: {response}")
|
||
|
||
# 解析响应消息
|
||
response_data = json.loads(response)
|
||
|
||
# 判断traceId是否匹配
|
||
if response_data.get("traceId") == "Access_Init":
|
||
# 再次获取当前的13位时间戳(毫秒级)以避免签名超时
|
||
current_time_sys_init = int(time.time() * 1000)
|
||
|
||
# 计算新的JSON数据的签名,参数post参数为"SysInit"
|
||
sys_init_sign = sign_GetSign(sign_key.decode('utf-8'), "SysInit", current_time_sys_init, sha256)
|
||
|
||
# 发送新的JSON数据
|
||
new_message = {
|
||
"type": "Invoke_SaiNiu",
|
||
"traceId": "0470bf9489729b2e8a2126a04ab3e272",#自定义返回的traceId
|
||
"codeType": "Access",
|
||
"post": "SysInit",
|
||
"data": {
|
||
"number": 20,
|
||
"port": 3030,
|
||
"token": True,
|
||
"connect": True,
|
||
"disconnect": True,
|
||
"newMessage": True,
|
||
"groupMessage": True,
|
||
"notice": True,
|
||
"event": True,
|
||
"assistant": True
|
||
},
|
||
"time": current_time_sys_init,
|
||
"sign": sys_init_sign
|
||
}
|
||
|
||
await websocket.send(json.dumps(new_message))
|
||
print(f"Sent message: {new_message}")
|
||
except websockets.ConnectionClosed:
|
||
print("服务器关闭连接")
|
||
except Exception as e:
|
||
print(f"出现错误:{e}")
|
||
except websockets.InvalidURI as e:
|
||
print(f"ws地址无效: {e} 请检查WebSocket地址")
|
||
break
|
||
except ConnectionRefusedError as e:
|
||
print(f"连接被拒绝: {e} 服务器可能未运行或URI不正确。5秒后重试..")
|
||
await asyncio.sleep(5)
|
||
except OSError as e:
|
||
print(f"操作系统错误: {e} 服务器可能无法访问。5秒后重试..")
|
||
await asyncio.sleep(5)
|
||
except Exception as e:
|
||
print(f"发生意外错误:{e} Sign验证错误。5秒后重试..")
|
||
await asyncio.sleep(5)
|
||
|
||
# 运行异步主函数
|
||
if __name__ == "__main__":
|
||
asyncio.run(connect_to_websocket())
|
||
|
||
|
||
|