如何刷新 Python 套接字?

发布于 2024-08-10 01:25:29 字数 515 浏览 8 评论 0原文

我用Python编写了一个服务器,旨在以“标题:消息”的形式将数据发送到客户端,

我希望能够单独发送每条消息,以便客户端只需执行最少的工作即可读取“标头”和“消息”

不幸的是,我不知道如何正确刷新Python套接字,因此当我快速连续执行多个发送时,消息会集中在套接字缓冲区中并作为一个大块发送。

示例:

服务器发送...

socket.send ("header1:message1")
socket.send ("header2:message2")
socket.send ("header3:message3")

客户端接收... “header1:message1header2:message2header3:message3”

我想收到三条单独的消息,

header1:message1
header2:message2
header3:message3

我需要一种在每次发送后刷新的方法

I've written a server in Python that is meant to send data to the client in the form "Header:Message"

I would like to be able to have each message sent individually so that the client will need to perform minimal work in order to read the "header" and the "message"

Unfortunately, I can't figure out how to properly flush a python socket so when I have multiple sends execute in quick succession the messages get lumped together in the socket buffer and sent as one big chunk.

Example:

Server sends...

socket.send ("header1:message1")
socket.send ("header2:message2")
socket.send ("header3:message3")

Client receives...
"header1:message1header2:message2header3:message3"

I'd like to receive three individual messages

header1:message1
header2:message2
header3:message3

I need a way to flush after each send

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

流绪微梦 2024-08-17 01:25:29

我猜你正在通过 TCP 连接进行交谈。

你的方法有缺陷。 TCP 流被定义为字节流。您始终必须使用某种分隔符,并且可能不依赖网络堆栈来分隔消息。

如果您确实需要基于数据报的服务,请切换到 UDP。在这种情况下,您需要自己处理重传。

澄清一下:

正如您所期望的那样,刷新发送缓冲区通常会创建新的包。如果您的客户端足够快地读取这些包,您每次读取可能会收到一条消息。

现在想象一下您通过卫星链路进行通信。由于高带宽和延迟,卫星之前的最后一个路由器会等待很短的时间,直到缓冲区中有足够的数据并立即发送所有数据包。您的客户端现在将立即接收所有数据包,并将所有数据立即放入接收缓冲区中。于是你们的分离又消失了。

I guess you are talking over a TCP connection.

Your approach is flawed. A TCP stream is defined as a stream of bytes. You always have to use some sort of separator and may not rely on the network stack to separate your messages.

If you really need datagram based services switch to UDP. You'll need to handle retransmission yourself in that case.

To clarify:

Flushing the send buffer usually creates new packages, just as you expect. If your client reads these packages fast enough you may get one message per read.

Now imagine you communicate over a satellite link. Because of high bandwidth and latency, the last router before the sat waits a short time until enough data is in the buffer and sends all your packets at once. Your client will now receive all packets without delay and will put all the data in the receive buffer at once. So your separation is gone again.

糖果控 2024-08-17 01:25:29

您想要做的是将数据分成“批次”。

例如,每当您从文件中读取“行”时,您都是在“批量”操作。 “线”的定义是什么?它是一个以“\n”结尾的字节序列。另一个例子是:您从文件中读取了 64KiB“块”。什么定义了“块”?确实如此,因为每次读取 65536 字节。你想要一个可变长度的“块”吗?您只需在“块”前面加上其大小,然后读取“块”即可。 “aiff”文件(其实现也是 MS Windows 的 .wav 和 .avi 文件)和“mov”文件的组织方式类似。

这三种方法是组织字节流的最基本方法,无论使用何种介质:

  1. 记录分隔符
  2. 固定大小记录
  3. 以其大小为前缀的记录。

它们可以混合和/或修改。例如,您可以拥有“变量记录分隔符”,如 XML 读取器:从第一个 '<' 读取字节直到第一个“>”,在第一个“<”后添加斜杠并将其称为记录结束,读取流直到记录结束。这只是一个粗略的描述。

选择一种方法,并在编写器和读取器中实现它。如果您还记录了您的选择,则您刚刚定义了第一个协议。

What you are trying to do, is split your data into "batches".

For example, you are operating on "batches" whenever you read "lines" off a file. What defines a "line"? It's a sequence of bytes terminated by '\n'. Another example is: you read 64KiB "chunks" off a file. What defines a "chunk"? You do, since you read 65536 bytes every time. You want a variable length "chunk"? You just prefix your "chunk" with its size, then read the "chunk". "aiff" files (whose implementations are also the .wav and .avi files of MS Windows) and "mov" files are organized like that.

These three methods are the most fundamental methods to organize a stream of bytes, whatever the medium:

  1. record separators
  2. fixed size records
  3. records prefixed with their size.

They can be mixed and/or modified. For example, you could have "variable record separators", like an XML reader: read bytes from first '<' until first '>', add a slash after first '<' and call it end-of-record, read stream until end-of-record. That's just a crude description.

Choose a method, and implement it in both the writer and reader. If you also document your choices, you've just defined your first protocol.

悲喜皆因你 2024-08-17 01:25:29

我在“刷新”UDP 套接字的缓冲区时遇到了同样的问题,这是我的解决方案:

def empty(sock):
    """Empty the UDP buffer."""
    sock.setblocking(0)
    while True:
        try:
            sock.recv(1024)
        except BlockingIOError:
            sock.setblocking(1)
            return

I had the same problem to "flush" the buffer of a UDP socket, and here is my solution:

def empty(sock):
    """Empty the UDP buffer."""
    sock.setblocking(0)
    while True:
        try:
            sock.recv(1024)
        except BlockingIOError:
            sock.setblocking(1)
            return
时光倒影 2024-08-17 01:25:29

只需在每条消息后附加 \n ...
喜欢

socket.send ("header1:message1\n")
socket.send ("header2:message2\n")
socket.send ("header3:message3\n")

just append \n after every message...
like

socket.send ("header1:message1\n")
socket.send ("header2:message2\n")
socket.send ("header3:message3\n")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文