Python websockets keepalive ping 超时;没有收到关闭帧

Posted

技术标签:

【中文标题】Python websockets keepalive ping 超时;没有收到关闭帧【英文标题】:Python websockets keepalive ping timeout; no close frame received 【发布时间】:2021-10-29 13:46:00 【问题描述】:

我有 20 到 50 个用户,我想从他们那里获得有关他们是否连接到 Internet 或网络较弱的实时信息

我编写了一个 Python 脚本来检查连接并将信息发送到 Django django-channels 中的 Web 服务器 脚本从上午 9 点到下午 6 点在 Windows 调度程序中运行

脚本

    async def main():
        username = get_username()
        url = "/".format(LOG_SERVER, username)
        async with websockets.connect(url) as websocket:
            # send info to server
            while True:
                try:
                    loop = asyncio.get_event_loop()
                    data = await loop.run_in_executor(None, 
                                              lambda:get_data(username))
                    await websocket.send(json.dumps(data))
                    await asyncio.sleep(30)
                except websockets.ConnectionClosed as e:
                    print(f'Terminated', e)
                    continue
                except Exception as e:
                    logging.error(e)

if __name__ == "__main__":
    asyncio.run(main())

WebSockets 包:https://websockets.readthedocs.io/

每 30 秒发送一次信息 ping min、max、avg 并确保客户端只要连接到服务器就连接好了

Django 消费者

async def connect(self):
        try:
            self.username = self.scope['url_route']['kwargs']['username']
            await database_sync_to_async(self.update_user_incr)(self.username)
        except KeyError as e:
            pass
          ......
async def disconnect(self, close_code):
     
        try:
            if(self.username):
                await database_sync_to_async(self.update_user_decr)(self.username)
        except:
            pass
        .......

问题是python脚本偶尔会卡住消息

sent 1011 (unexpected error) keepalive ping timeout; no close frame received

no close frame received or sent

我不能自动回拨

我怎样才能保持连接打开或者如果它关闭它会在一小部分时间内重新打开,以便前端无法修改在线或离线指示器

【问题讨论】:

【参考方案1】:

我最终重新连接了这样的东西

 async for websocket in websockets.connect(url):
        try:
            loop = asyncio.get_event_loop()
            data = await loop.run_in_executor(None, lambda: get_data(username))
            await websocket.send(json.dumps(data))
            await asyncio.sleep(30)
        except websockets.ConnectionClosed as e:
            print(f'Terminated', e)

但是我遇到了一个问题,那就是在每个连接上调整用户状态。在这种情况下,您可以使用这个blog 和这个answer 来减轻数据库的负载

【讨论】:

以上是关于Python websockets keepalive ping 超时;没有收到关闭帧的主要内容,如果未能解决你的问题,请参考以下文章

python2.7 websocket

python版websocket

python之websocket

python与html5 websocket开发聊天对话窗

python-websocket-server hacking

python---websocket的使用