多线程的 udp client server 测试demo

简介: 本示例展示了使用 Python 实现的 UDP 客户端与服务端通信,支持多线程、线程池、JSON 格式传输、UUID 生成、超时设置及 search_id 校验功能,适用于高并发场景下的数据交互需求。



架构图


image.png




交互泳道图


image.png




以下是一个完整的 UDP 客户端与服务端 示例,完全满足以下需求:


✅ 功能说明

功能 描述
UDP 通信 使用 socket.SOCK_DGRAM 实现无连接 UDP 通信
JSON 格式 请求与响应均使用 JSON 格式传输
客户端多线程 同时启动多个客户端线程发送请求
UUID 生成 客户端随机生成 search_id 字段
服务端线程池 使用 ThreadPoolExecutor 并发处理请求
客户端超时设置 客户端设置响应等待超时(默认 5 秒)
search_id 校验 客户端验证响应中的 search_id 是否匹配请求



🧩 服务端代码(支持线程池)


server端代码


import socket
import json
import uuid
from concurrent.futures import ThreadPoolExecutor

# 服务端配置
HOST = '127.0.0.1'
PORT = 9999
MAX_BUFFER_SIZE = 4096
MAX_THREADS = 500  # 最大并发线程数

# 创建 UDP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind((HOST, PORT))
print(f"UDP 服务端启动,监听地址 {HOST}:{PORT}")

# 使用线程池处理请求
executor = ThreadPoolExecutor(max_workers=MAX_THREADS)

def handle_request(data, client_address):
    try:
        # 解析 JSON 请求
        request = json.loads(data.decode('utf-8'))
        search_id = request.get('search_id')
        message = request.get('message', '')
        print(f"[请求] 来自 {client_address},search_id: {search_id}")

        # 构造响应
        response = {
            "status": "success",
            "search_id": search_id,
            "message": f"已收到请求: {message}"
        }

        json_response = json.dumps(response).encode('utf-8')
        server_socket.sendto(json_response, client_address)
        print(f"[响应] 发送至 {client_address},search_id: {search_id}")
    except json.JSONDecodeError:
        print(f"[错误] 接收的不是有效的 JSON 数据,来自 {client_address}")
    except Exception as e:
        print(f"[异常] 处理请求时发生错误: {e}")

# 主循环接收请求
try:
    while True:
        data, client_address = server_socket.recvfrom(MAX_BUFFER_SIZE)
        executor.submit(handle_request, data, client_address)
except KeyboardInterrupt:
    print("\n服务端关闭。")
    server_socket.close()


📡 客户端代码(支持多线程 + UUID + 超时 + search_id 校验)


client 端代码

import socket
import json
import uuid
import threading
import time
import random

# 客户端配置
SERVER_HOST = '127.0.0.1'
SERVER_PORT = 9999
CLIENT_THREADS = 500  # 客户端线程数
TIMEOUT = 5  # 超时时间(秒)
MAX_BUFFER_SIZE = 32000

def client_thread_func(thread_id):
    # 每个线程使用自己的 socket
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client_socket.settimeout(TIMEOUT)

    # 生成随机 UUID 作为 search_id
    search_id = str(uuid.uuid4())
    request = {
        "search_id": search_id,
        "message": f"这是来自线程 {thread_id} 的请求"
    }
    json_request = json.dumps(request).encode("utf-8")
    t1 = time.time()
    print(f"[客户端线程 {thread_id}] 发送请求,search_id: {search_id}")
    client_socket.sendto(json_request, (SERVER_HOST, SERVER_PORT))

    try:
        # 等待响应
        response_data, server_address = client_socket.recvfrom(MAX_BUFFER_SIZE)
        response = json.loads(response_data)
        print(f"[客户端线程 {thread_id}] 收到响应: {response}")
        t2 = time.time()
        time_use_ms = round(1000*(t2-t1), 3)
        # 校验 search_id
        if 'search_id' not in response:
            print(f"[客户端线程 {thread_id}] 响应中缺少 search_id 字段! time_use_ms: {time_use_ms}")
        elif response['search_id'] != search_id:
            print(f"[客户端线程 {thread_id}] 错误!search_id 不匹配。发送的: {search_id},返回的: {response['search_id']}. time_use_ms: {time_use_ms}")
        else:
            print(f"[客户端线程 {thread_id}] search_id 校验通过。 time_use_ms: {time_use_ms}")
        
    except socket.timeout:
        print(f"[客户端线程 {thread_id}] 超时,未收到响应。")
    except json.JSONDecodeError:
        print(f"[客户端线程 {thread_id}] 接收到的响应不是有效的 JSON 数据。")
    except Exception as e:
        print(f"[客户端线程 {thread_id}] 发生异常: {e}")
    finally:
        client_socket.close()

# 启动多个客户端线程
threads = []
for i in range(CLIENT_THREADS):
    t = threading.Thread(target=client_thread_func, args=(i,))
    threads.append(t)
    t.start()
    # 随机延迟
    time.sleep(random.uniform(0.0001, 0.001))

# 等待所有线程完成
for t in threads:
    t.join()

print("所有客户端线程执行完毕。")



🧪 运行方式

  1. 先启动服务端
  2. bash
  3. 深色版本
python server.py
  1. 再运行客户端
  2. bash
  3. 深色版本
python client.py



📌 示例输出

服务端输出(线程池处理):


深色版本

UDP 服务端启动,监听地址 127.0.0.1:9999
[请求] 来自 ('127.0.0.1', 65432),search_id: 123e4567-e89b-12d3-a456-426614174000
[响应] 发送至 ('127.0.0.1', 65432),search_id: 123e4567-e89b-12d3-a456-426614174000

客户端输出(正常响应):


深色版本

[客户端线程 0] 发送请求,search_id: a1b2c3d4-e5f6-7890-abcd-1234567890ab
[客户端线程 0] 收到响应: {'status': 'success', 'search_id': 'a1b2c3d4-e5f6-7890-abcd-1234567890ab', 'message': '已收到请求: 这是来自线程 0 的请求'}
[客户端线程 0] search_id 校验通过。

客户端输出(超时场景):


深色版本

[客户端线程 1] 发送请求,search_id: 98765432-1098-7654-3210-09876543210a
[客户端线程 1] 超时,未收到响应。

🧠 技术要点说明

组件 说明
服务端线程池 使用 ThreadPoolExecutor 并发处理请求,避免阻塞主线程
客户端多线程 每个线程使用独立 socket,避免通信冲突
UUID 生成 使用 uuid.uuid4() 生成唯一标识
JSON 格式 使用 json.dumps()json.loads() 实现序列化/反序列化
客户端超时 使用 socket.settimeout() 设置响应等待时间
search_id 校验 客户端验证响应中的 search_id 是否与请求一致


🔒 注意事项

  • 防火墙/网络环境:确保本地网络允许 UDP 通信(尤其在跨设备通信时)。
  • 数据大小限制:建议控制在 1472 字节以内以避免分片。
  • 线程池大小:根据实际负载调整 MAX_THREADS
  • UUID 唯一性uuid.uuid4() 生成的 UUID 是全局唯一的。



相关文章
|
9月前
|
人工智能 自然语言处理 JavaScript
利用MCP Server革新软件测试:更智能、更高效的自动化
MCP Server革新软件测试:通过标准化协议让AI实时感知页面结构,实现自然语言驱动、自适应维护的自动化测试,大幅提升效率,降低脚本开发与维护成本,推动测试左移与持续测试落地。
|
测试技术 Go 开发者
如何为 gRPC Server 编写本地测试代码
本文介绍了如何使用 Go 语言中的 gRPC 测试工具 **bufconn**,通过内存连接实现 gRPC Server 的本地测试,避免端口冲突和外部依赖。结合示例代码,讲解了初始化内存监听、自定义拨号器及编写测试用例的完整流程,并借助断言库提升测试可读性与准确性。适用于单元及集成测试,助力高效开发。
286 1
|
存储 前端开发 JavaScript
VSCode调试揭秘:Live Server助力完美测试Cookie与Session,远超“Open in Browser“!
VSCode调试揭秘:Live Server助力完美测试Cookie与Session,远超“Open in Browser“!
|
Linux C#
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
249 0
|
存储 Kubernetes 安全
虚拟机测试Windows Server 2016原地升级2019,应用和数据完美保留
Windows Server 2016可以无缝升级到2019版本,确保应用程序和数据在原地升级过程中完整保留。
1774 0
|
Java 应用服务中间件 Spring
WebService - CXF开发Server和Client(main方法测试)
WebService - CXF开发Server和Client(main方法测试)
447 0
|
网络协议 Linux 测试技术
我个人的Linux TCP server和client测试源码,C语言(2)(★firecat推荐★)
我个人的Linux TCP server和client测试源码,C语言(2)(★firecat推荐★)
747 0
我个人的Linux TCP server和client测试源码,C语言(2)(★firecat推荐★)
|
JSON 前端开发 数据格式
使用Mock.js和json server快速生成前端测试数据
使用Mock.js和json server快速生成前端测试数据
485 0
使用Mock.js和json server快速生成前端测试数据
|
网络架构 Windows
使用Windows Server 2012 R2创建DHCP作用域(DHCP地址池),并测试使用
使用Windows Server 2012 R2创建DHCP作用域(DHCP地址池),并测试使用
589 0
|
网络协议 Linux C语言
我个人的Linux TCP server和client测试源码,C语言(2)(★firecat推荐★)
我个人的Linux TCP server和client测试源码,C语言(2)(★firecat推荐★)
273 0