为什么WebSocket连接Discord网关后需要20-30秒才进入while循环处理消息
问题原因
- 你当前调用的
recieve_json_response(ws)是阻塞式WebSocket接收方法,没有新消息推送的时候会一直挂起等待,直到收到新的网关事件才会返回,才会执行后面的print("Entered While Loop")语句,这就是你感知到卡顿的核心原因。 - 你调用的Discord网关地址里存在拼写错误:
encording=json应为encoding=json,错误参数可能导致网关返回异常、事件推送延迟。 - 你没有正确订阅消息相关的网关意图(Intents),Discord v6及更高版本的网关需要在鉴权payload里声明
intents字段,接收频道消息需要开启对应GUILD_MESSAGES的意图值,未开启的情况下网关不会推送消息事件,只能等到心跳包或其他系统事件才会返回,自然会出现几十秒的等待。 - 现有代码没有对事件类型做过滤,遇到非消息类的系统事件时会抛出字段不存在的异常,也会影响执行效率。
解决方案
- 先修正网关地址的拼写错误,把
encording修改为encoding。 - 在鉴权payload里增加
intents字段,接收服务器频道消息可以赋值为512,需要同时接收私信的话可以赋值为512 | 4096。 - 如果要避免接收函数完全阻塞主线程,可以把WebSocket接收逻辑单独放到子线程运行,或者给WebSocket的recv操作设置超时时间,每次超时后继续循环,不会一直挂起。
- 处理事件时先判断
op字段:op=0才是普通的分发事件,再判断事件类型为MESSAGE_CREATE才做消息匹配,避免遇到系统事件抛出异常。
修正后的核心代码参考:
ws.connect('wss://gateway.discord.gg/?v=6&encoding=json') # 修正拼写错误 print("Connected") event = recieve_json_response(ws) heartbeat_interval = event['d']['heartbeat_interval'] / 1000 threading._start_new_thread(heartbeat, (heartbeat_interval, ws)) print("Interval Set") token = dtoken payload = { 'op': 2, "d": { "token": token, "properties": { "$os": "windows", "$browser": "chrome", "$device": 'pc' }, "intents": 512 # 新增消息意图,可根据实际需求调整值 } } send_json_request(ws, payload) print("Sent Request") while True: event = recieve_json_response(ws) print("Entered While Loop") try: print("Entered Try Loop") # 过滤非分发事件 if event['op'] != 0: continue # 过滤非消息创建事件 if event['t'] != 'MESSAGE_CREATE': continue if event['d']["channel_id"] == channelid: if "https" in event['d']['content']: pair = event['d']['content'].rsplit('/', 1)[1] print("U R DUMB") break except KeyError: # 字段缺失直接跳过,避免程序异常退出 continue
内容的提问来源于stack exchange,提问作者Zayous
相关产品推荐
相关产品推荐

