You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python下基于TCP协议异步读取以太网数据的方案咨询

Python异步读取TCP Socket数据方案推荐

你当前使用同步while循环阻塞读取TCP数据,确实不够高效。以下是几种无需手动轮询、能在socket有数据时自动触发读取的异步方案:

方法一:使用标准库asyncio(推荐)

asyncio是Python官方异步I/O框架,基于事件驱动模型,无需手动维护轮询循环,当socket有数据可读时会自动唤醒读取逻辑。

结合你的现有代码修改后的示例:

import asyncio
import socket
import sys
import codecs
import binascii
import struct
import time, datetime
import array

HOST = "192.24.134.1"  # 服务器IP或主机名
PORT = 10943            # 服务器端口
ADDR=(HOST,PORT)
ID=43
cmd=2
CMDm=cmdf.cfg(cmd,ID) # 生成待发送的TCP数据包

async def tcp_client():
    # 建立异步TCP连接
    reader, writer = await asyncio.open_connection(HOST, PORT)
    
    # 发送命令包
    writer.write(CMDm)
    await writer.drain()
    
    # 异步读取数据:当socket有数据时自动执行,无数据时释放事件循环资源
    while True:
        data = await reader.read(2000)
        if not data:
            break  # 连接关闭时退出
        # 这里添加你的数据处理逻辑
        print(f"收到数据: {data}")
    
    # 关闭连接
    writer.close()
    await writer.wait_closed()

# 启动异步事件循环
asyncio.run(tcp_client())

这里的await reader.read(2000)是非阻塞调用,事件循环会在socket无数据时处理其他任务,有数据时才继续执行读取操作,无需手动轮询。

方法二:使用标准库selectors(底层控制)

selectors基于操作系统I/O多路复用机制(如epoll、kqueue),可以监听socket的可读事件,触发回调函数处理数据,适合需要底层控制的场景。

示例代码:

import selectors
import socket
import sys
import codecs
import binascii
import struct
import time, datetime
import array

HOST = "192.24.134.1"
PORT = 10943
ADDR=(HOST,PORT)
ID=43
cmd=2
CMDm=cmdf.cfg(cmd,ID)

# 创建系统默认的selector实例
sel = selectors.DefaultSelector()

def handle_data(sock, mask):
    """socket可读时触发的回调函数"""
    data = sock.recv(2000)
    if data:
        # 处理收到的数据
        print(f"收到数据: {data}")
    else:
        # 连接关闭,取消监听并关闭socket
        sel.unregister(sock)
        sock.close()

def main():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(ADDR)
    client.setblocking(False)  # 设置为非阻塞模式
    # 发送命令包
    client.send(CMDm)
    # 注册socket的可读事件,绑定回调函数
    sel.register(client, selectors.EVENT_READ, handle_data)
    
    # 事件循环:自动监听socket事件,有数据时触发回调
    while True:
        events = sel.select()
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)

if __name__ == "__main__":
    main()

sel.select()会阻塞直到有socket事件发生,无需手动检查socket是否有数据,完全由系统通知触发读取。

方法三:第三方库trio(简洁高效)

trio是现代异步I/O库,API设计更简洁直观,错误处理更友好,适合复杂异步场景。需要先通过pip install trio安装。

示例代码:

import trio
import socket
import sys
import codecs
import binascii
import struct
import time, datetime
import array

HOST = "192.24.134.1"
PORT = 10943
ADDR=(HOST,PORT)
ID=43
cmd=2
CMDm=cmdf.cfg(cmd,ID)

async def tcp_client():
    async with await trio.open_tcp_stream(HOST, PORT) as stream:
        # 发送命令包
        await stream.send_all(CMDm)
        # 异步读取数据,有数据时自动返回
        while True:
            data = await stream.receive_some(2000)
            if not data:
                break
            # 处理数据
            print(f"收到数据: {data}")

# 启动trio事件循环
trio.run(tcp_client)

trio的receive_some方法会在socket有数据时立即返回,无数据时释放事件循环资源,无需手动轮询。


内容的提问来源于stack exchange,提问作者Sugandh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:58:21