websockets处理流式接口

server.py

复制代码
#!/usr/bin/env python

import asyncio
import json
import time
from websockets.asyncio.server import serve

async def stream_data(websocket):
    """流式发送数据的处理函数"""
    # 接收客户端的初始消息
    try:
        message = await websocket.recv()
        print(f"<<< 收到客户端消息: {message}")
        
        # 解析客户端请求
        try:
            request = json.loads(message)
            stream_type = request.get('type', 'text')
            count = request.get('count', 10)
        except json.JSONDecodeError:
            stream_type = 'text'
            count = 10
        
        print(f"开始流式发送 {count} 条 {stream_type} 数据...")
        
        # 根据不同类型流式发送数据
        if stream_type == 'text':
            # 文本流式传输
            for i in range(count):
                response = {
                    'type': 'text',
                    'data': f'这是第 {i+1} 条文本消息',
                    'timestamp': time.time(),
                    'progress': f'{i+1}/{count}'
                }
                await websocket.send(json.dumps(response, ensure_ascii=False))
                print(f">>> 发送: {response['data']}")
                await asyncio.sleep(1)  # 模拟延迟
                
        elif stream_type == 'number':
            # 数字流式传输
            for i in range(count):
                response = {
                    'type': 'number',
                    'data': i + 1,
                    'square': (i + 1) ** 2,
                    'timestamp': time.time(),
                    'progress': f'{i+1}/{count}'
                }
                await websocket.send(json.dumps(response))
                print(f">>> 发送数字: {response['data']}")
                await asyncio.sleep(0.5)
                
        elif stream_type == 'json':
            # JSON数据流式传输
            sample_data = [
                {'id': 1, 'name': '张三', 'age': 25, 'city': '北京'},
                {'id': 2, 'name': '李四', 'age': 30, 'city': '上海'},
                {'id': 3, 'name': '王五', 'age': 28, 'city': '广州'},
                {'id': 4, 'name': '赵六', 'age': 35, 'city': '深圳'},
                {'id': 5, 'name': '钱七', 'age': 22, 'city': '杭州'}
            ]
            
            for i, item in enumerate(sample_data[:count]):
                response = {
                    'type': 'json',
                    'data': item,
                    'index': i,
                    'total': len(sample_data[:count]),
                    'progress': f'{i+1}/{len(sample_data[:count])}'
                }
                await websocket.send(json.dumps(response, ensure_ascii=False))
                print(f">>> 发送JSON数据: {item}")
                await asyncio.sleep(1.5)
        
        # 发送结束信号
        end_message = {
            'type': 'end',
            'message': '数据传输完成',
            'total_sent': count,
            'timestamp': time.time()
        }
        await websocket.send(json.dumps(end_message, ensure_ascii=False))
        print(">>> 数据传输完成")
        
    except Exception as e:
        print(f"处理客户端连接时出错: {e}")
        error_response = {
            'type': 'error',
            'message': str(e),
            'timestamp': time.time()
        }
        await websocket.send(json.dumps(error_response, ensure_ascii=False))

async def main():
    print("WebSocket流式服务器启动中...")
    print("支持的流式类型: text(文本), number(数字), json(JSON数据)")
    print("请使用客户端连接 localhost:8765")
    
    async with serve(stream_data, "localhost", 8765) as server:
        await server.serve_forever()

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n服务器已停止")

client.py

复制代码
#!/usr/bin/env python

import asyncio
import json
import websockets

# 全局变量存储WebSocket连接
_global_websocket = None
_global_uri = "ws://localhost:8765"

async def get_websocket_connection():
    """获取全局WebSocket连接,只连接一次"""
    global _global_websocket
    
    if _global_websocket is None:
        print("正在建立WebSocket连接...")
        _global_websocket = await websockets.connect(_global_uri)
        print(f"已连接到服务器: {_global_uri}")
    
    return _global_websocket

async def close_websocket_connection():
    """关闭全局WebSocket连接"""
    global _global_websocket
    
    if _global_websocket is not None:
        await _global_websocket.close()
        _global_websocket = None
        print("WebSocket连接已关闭")

async def reset_websocket_connection():
    """重置全局WebSocket连接"""
    global _global_websocket
    _global_websocket = None

async def test_stream_client(stream_type="text", count=5):
    """测试流式数据接收的客户端"""
    
    try:
        # 获取全局连接(只连接一次)
        websocket = await get_websocket_connection()

        # 发送请求配置
        request = {
            "type": stream_type,
            "count": count
        }
        await websocket.send(json.dumps(request))
        print(f"已发送请求: {request}")

        # 接收流式数据
        received_count = 0
        while True:
            try:
                message = await websocket.recv()
                data = json.loads(message)

                if data['type'] == 'end':
                    print(f"\n✅ 传输完成! 总共接收 {data.get('total_sent', 0)} 条数据")
                    break
                elif data['type'] == 'error':
                    print(f"\n❌ 错误: {data['message']}")
                    break
                else:
                    received_count += 1
                    print(f"\n📥 第 {received_count} 条数据:")
                    print(f"   类型: {data['type']}")
                    print(f"   内容: {data['data']}")
                    print(f"   进度: {data.get('progress', 'N/A')}")
                    if 'timestamp' in data:
                        print(f"   时间戳: {data['timestamp']}")

            except websockets.exceptions.ConnectionClosed:
                print("连接已关闭")
                # 重置全局连接
                await reset_websocket_connection()
                break

    except Exception as e:
        print(f"连接错误: {e}")
        # 出错时重置连接
        await reset_websocket_connection()

async def interactive_client():
    """交互式客户端"""
    print("=== WebSocket流式数据客户端 ===")
    print("支持的类型: text(文本), number(数字), json(JSON数据)")
    print("注意: WebSocket连接只会建立一次")

    try:
        while True:
            stream_type = "text"
            if stream_type == 'quit':
                break

            count_input = input("请输入要接收的数据条数 (默认5): ").strip()
            count = int(count_input) if count_input.isdigit() else 5

            print(f"\n开始接收 {count} 条 {stream_type} 类型的数据...")
            await test_stream_client(stream_type, count)

            print("继续执行")

    except KeyboardInterrupt:
        print("\n客户端已退出")
    except Exception as e:
        print(f"发生错误: {e}")
    finally:
        # 程序结束时关闭连接
        await close_websocket_connection()

if __name__ == "__main__":
    # 可以选择运行交互式客户端或直接测试
    # choice = input("选择模式 - 1: 交互式, 2: 直接测试text类型 (默认1): ").strip()
    #
    # if choice == "2":
    #     # 直接测试
    #     asyncio.run(test_stream_client("text", 3))
    # else:
    #     # 交互式模式
    #     asyncio.run(interactive_client())
    asyncio.run(interactive_client())
相关推荐
郝学胜-神的一滴2 分钟前
Pytorch自动微分模块:从原理到实战,解锁反向传播核心奥秘
服务器·人工智能·pytorch·python·深度学习·机器学习
minji...6 分钟前
Linux 多线程(三)线程控制,线程终止,线程中的异常问题
linux·运维·服务器·开发语言·网络·算法
KhalilRuan7 分钟前
HybridCLR的底层原理
java·开发语言
Miki Makimura9 分钟前
C++ 聊天室项目:Linux 环境搭建与问题总结
linux·开发语言·c++
CappuccinoRose11 分钟前
排序算法和查找算法 - 软考备战(十五)
数据结构·python·算法·排序算法·查找算法
tq6J5Yg1411 分钟前
.NET 10 & C# 14 New Features 新增功能介绍-带修饰符的简单 lambda 参数
开发语言·c#·.net
jinanwuhuaguo12 分钟前
OpenClaw办公人员核心技能深度培训体系:从认知重塑到数字组织构建的全链路实战指南
java·大数据·开发语言·人工智能·openclaw
郝学胜-神的一滴14 分钟前
[简化版 GAMES 101] 计算机图形学 03:线性代数下
开发语言·c++·线性代数·图形渲染
Dxy123931021615 分钟前
如何使用 ECharts 绘制 K 线图
开发语言·javascript
fe7tQnVan16 分钟前
从玩具到生产:基于 ChromaDB 打造工程级 RAG 系统
开发语言·c#