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