websocket创建客户端的两种方式及区别

背景

需要创建一个ws客户端mock弹幕一直给直播间发送消息。于是使用了async with websockets.connect(uri) as websocket 创建的ws客户端发送消息。但是发现发送一会儿后,客户端就自动关闭了,曝出:“websockets.ConnectionClosedError, WebSocket连接关闭: no close frame received or sent”

即:websocket.connect(url) as websocket 返回的异步上下文管理器对象。发收到发送一会儿消息后,客户端自动化关闭链接,导致报错。为什么?

原理

ws是基于tcp协议的信令通道。使用流程:

1、ws握手:

客户端主动创建ws连接,例如通过url: ws://127.0.0.1:8888创建ws连接。

2、发送数据:

发送信令数据包,Server如果长时间没有收到数据,会主动断开ws连接。这应该就是背景中自动关闭连接的原因。所以如果不说固定频率时间的发送信息,可以发送心跳包活包。

验证发现每隔2s就发送信息,连接就会一直连接。

使用式例代码如下“式例代码”。

实现websocket客户端

方式1:用websocket.WebSocketApp创建。通过定义回调函数来处理不同的事件,如接受消息、发生错误、连接关闭等。

ws = websocket.WebSocketApp("ws_barrage_mock://example.com",
                            on_message=on_message,
                            on_error=on_error,
                            on_close=on_close,
                            on_open=on_open)

在如下示例send_message()中进行死循环,在新开一个进程中进行发送消息。

方式2: 使用异步ws对象,同时进行发送心跳(目前代码里没有实现)

async with websockets.connect("ws_bk://127.0.0.1:8888") as websocket:

式例代码

ws_server.py

import asyncio
import websockets

# 保存已连接的客户端列表
connected_clients = set()

async def handle_websocket(websocket, path):
    # 将新的客户端添加到已连接客户端列表
    remote_address = websocket.remote_address
    connected_clients.add(websocket)
    print(f"新的客户端已连接:{remote_address}")

    try:
        # 接收客户端消息并发送回复
        async for message in websocket:
            print(f"收到客户端{remote_address}消息:{message}")
            # 广播发送消息给所有客户端
            await broadcast(message)
    except websockets.ConnectionClosedError:
        print(f"客户端{remote_address}连接关闭")
    except Exception as e:
        print(f"处理客户端时出现错误:{e}")
    finally:
        # 从已连接客户端列表中移除客户端
        connected_clients.remove(websocket)

async def broadcast(message):
    # 遍历所有已连接的客户端,并发送消息
    for client in connected_clients:
        await client.send(message)

async def main():
    # 创建WebSocket服务器并注册处理程序
    server = await websockets.serve(handle_websocket, "127.0.0.1", 8888)

    # 运行服务器
    await server.wait_closed()

# 运行主函数
asyncio.run(main())

web_client_webapp.py

import websocket

def on_message(ws, message):
    print(f"Received message: {message}")

def on_error(ws, error):
    print(f"Error: {error}")

def on_close(ws):
    print("Connection closed")

def on_open(ws):
    print("Connection opened")
    ws.send("Hello, server!")

websocket.enableTrace(True)  # 启用调试日志

ws = websocket.WebSocketApp("ws_barrage_mock://example.com",
                            on_message=on_message,
                            on_error=on_error,
                            on_close=on_close,
                            on_open=on_open)

ws.run_forever()

web_client_async.py

import asyncio
import websockets

async def receive_msg(websocket):
    while True:
        reply = await websocket.recv()
        print(f"收到服务器回复:{reply}")

async def send_message(websocket):
    while True:
        # message = ''
        # while '1' not in message \
        #         and '2' not in message \
        #         and '3' not in message \
        #         and '4' not in message \
        #         and '5' not in message:
        #     message = input("请输入要发送的消息,输入\n"
        #                     "(1)弹幕消息\n"
        #                     "(2)点赞消息\n"
        #                     "(3)进直播间\n"
        #                     "(4)关注消息\n"
        #                     "(5)礼物消息:\n")
        # print(f'-->输入成功:{message}\n')
        message = '1'
        await websocket.send(pkg_msg(message))
        print('发送消息:', pkg_msg(message))
        await asyncio.sleep(2)


async def asyncio_tasks(url):
    try:
        async with websockets.connect(url) as websocket:

            # 启动发送消息的任务
            send_task = asyncio.create_task(send_message(websocket))
            # 启动接收消息的任务
            receive_task = asyncio.create_task(receive_msg(websocket))

            # 等待两个任务完成
            await asyncio.gather(send_task, receive_task)
    except websockets.ConnectionClosedError as e:
        print(f"WebSocket连接关闭: {e}")


# 示例使用
asyncio.run(asyncio_tasks("ws://127.0.0.1:8888"))

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebSocket是一种全双工通信协议,可以通过Web服务器与客户端建立持久连接,实现实时通信。在C语言中实现WebSocket客户端需要使用相应的库。 首先,我们需要选择一个WebSocket库进行C语言开发,常用的库有libwebsockets和uWebSockets。这两个库都提供了C语言的API,能够方便地实现WebSocket客户端功能。 接下来,我们需要进行以下步骤来编写WebSocket客户端。 1. 引入WebSocket库:根据选择的库和开发环境,将相应的库文件添加到项目中,并将头文件包含到源代码中。 2. 初始化WebSocket连接:创建一个WebSocket连接的客户端对象,并设置连接的一些参数,例如服务器地址、端口号等。 3. 建立连接:通过调用相应的函数与WebSocket服务器建立连接,并等待连接的建立成功。 4. 发送和接收数据:使用WebSocket客户端对象提供的函数,可以发送和接收WebSocket协议规定的数据帧。例如,通过发送文本数据帧实现向服务器发送消息,并通过接收文本数据帧接收服务器返回的数据。 5. 保持连接:在整个会话期间,需要保持WebSocket连接的持续性,以便实现实时通信。可以通过定时发送心跳数据帧或者检测服务器发送的心跳数据帧来保持连接的活跃性。 6. 断开连接:当通信完成或者需要关闭WebSocket连接时,调用相应的函数断开连接,并释放资源。 通过以上步骤,我们可以实现一个基本的WebSocket客户端。根据具体需求,还可以对WebSocket客户端进行进一步的功能扩展,如支持SSL/TLS安全连接、添加回调函数处理各种事件等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值