Files

174 lines
6.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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())