python - 如何将 UDP 与 Asyncio 一起用于从服务器到客户端的多个文件传输 - python

标签 python python-3.x multithreading python-asyncio

我想从服务器向客户端传输数据(多张大小 > 3 MB 的图像)。由于我想测试没有重传的丢包,所以我不想使用流(TCP)。

我经历了这个example .我的方法是,服务器使用 f.read(1024) 读取数据 block 并使用 transport.sendto(data + seq_num) 发送给客户端。读取和发送将循环进行,直到文件结束。 客户端将通过 datagram_received(self, data, addr): 接收。由于我在数据中发送序列号 (seq_num),因此我可以控制丢失的段和顺序.我的问题是在客户端接收和写入数据。如何使用 datagram_received (self, data, addr) 函数在客户端存储不同时间从服务器发送的数据?

是否有用于从 sock 接收数据到 buf 缓冲区的功能?例如,对于流 (TCP) data = await loop.sock_recv(tcp_sock, buf)。感谢您的帮助。

最佳答案

Is there a feature that used to receive data from sock into the buf buffer? e.g for stream (TCP) data = await loop.sock_recv(tcp_sock, buf).

正如评论中所指出的,数据报无法提供真正的流接口(interface),因为 UDP 不保证传递顺序。如果我对问题的理解正确,您会希望有一个可等待接口(interface)来处理下一个 UDP 数据包的传送事件,因为默认提供的接口(interface)完全基于回调。

幸运的是,将基于回调的接口(interface)转换为可等待的接口(interface)非常容易 - asyncio 通常为此目的使用 Future,协程等待 future ,并且回调调用 set_result() 将一些数据传递给等待协程 - 请参阅 sample UDP client 中的 on_con_lost来自文档。

一个好的流式 API 总是支持某种形式的缓冲,这可以由容量有限的队列提供:

class Client:
    def __init__(self):
        self._received = asyncio.Queue(10)
        ...

    async def read_packet(self):
        return await self._received.get()

    def datagram_received(self, data, addr):
        try:
            self._received.put_nowait((data, addr))
        except asyncio.QueueFull:
            log.error(f"dropped packet size {len(data)} from {addr}")

有限大小的队列允许数据处理暂时慢于数据到达的速度,同时防止内存泄漏,以防情况继续发生。队列填满后,数据包将被丢弃。 (对于 TCP/IP 支持的流,我们会减慢读取速度以提供背压 - 在 this article 中有很好的解释,但对于 UDP,除了放弃别无选择。)

关于python - 如何将 UDP 与 Asyncio 一起用于从服务器到客户端的多个文件传输 - python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53733140/

相关文章:

c++ - 为什么在删除原子引用计数智能指针中的数据之前需要获取屏障?

python - 在 Scrapy 中利用 Beautifulsoup

python - 获取最终预测蒙版中的轮廓坐标

python - 从 Python 中编译的正则表达式中提取命名组正则表达式模式

ios - 将单独线程检索的数据返回到主线程以在 UI 中显示

c++ - 我可以将 QObject 的两个子类移动到同一个 QThread 吗?

python - anaconda+sublimetext,报告类型提示为错误

python - 如何在odoo中使用onchange存储值?

python - 使用 parsimonious 解析势函数的参数

python - 在python中通过json递归