ipc - 数据包通过命名管道传输?单字节缓冲区还是预先确定大小?

标签 ipc buffer named-pipes

我想通过命名管道在两个程序之间发送数据“包”(即离散消息)。考虑到我必须提供一个缓冲区和一个缓冲区大小来读取,并且考虑到读取命令是阻塞的(我相信),我要么必须有一个缓冲区大小来保证我永远不会低于-run,或者预先知道消息的大小。我不希望发送程序必须知道缓冲区的大小并将其填充。

据我所知,可以通过三种方法来做到这一点。

  1. 在每个包前面加上要发送的消息的大小,以便监听程序可以读取那么多字节。
  2. 一次从管道读取一个字节并监听特殊的流结束值。
  3. 更好的方法

在第一种情况下,我将能够创建一个已知大小的缓冲区并立即读入其中。在第二种情况下,我必须使用一字节缓冲区进行读取。这可能要么完全没问题,要么就是一场极其低效的 mock 。

我选择第二种方法的唯一原因是为了更灵活的输入(例如,如果我想要的话,可以进行手动交互)。

哪条路最好?

最佳答案

使用命名管道,读取和写入是(或可以)原子的。在限制范围内,如果您向管道写入 1024 字节,则另一端查找至少 1024 字节的读取调用实际上将收到 1024 字节,即使当时管道中有更多数据。所读的。此外,如果命名管道中只有 1024 字节并且读取请求 4096 字节,那么它将在第一次尝试时获取 1024 字节,并且仅在后续尝试时阻塞。

你说:

Given that I have to supply a buffer and a buffer size to read,

你确实...

and given that the read command is blocking (I believe),

是的,除非你在文件描述符上设置 O_NONBLOCK...

I either have to have a buffer size that guarantees I never get an under-run,

您要发送什么类型的消息?您要处理的尺寸是多少?千字节、兆字节还是更大?

or to know the size of the message up-front.

在阅读器中拥有 4KB 缓冲区并以 block 的形式读取消息并没有什么特别的问题。问题在于知道您何时到达消息末尾。到目前为止,大多数协议(protocol)都需要预先指定长度,因为它可以轻松可靠地编写阅读器代码。

如果您要进行“流结束”(EOS) 标记,那么您就是在进行“带内信令”。这会带来麻烦。您要使用什么角色?当该字符出现在数据中时会发生什么?您需要一个转义机制,例如表示“下一个字符不是 EOS 标记”的字符。例如,在与编程相关的文本中,反斜杠就是用于此目的。在终端,control-V 通常可以达到目的。

I don't want the sending program to have to know the size of the buffer and pad it out.

为什么发送方很难知道缓冲区的大小?为什么需要“填充它”?

如果您正在处理大量数据(例如千字节以上),单字符解决方案不太可能产生可接受的性能。我认为最好让发送者能够确定数据包的大小并告诉读者,或者设计协议(protocol)以限制数据包的大小。如果您需要传输任意数量的数据,请制定一个协议(protocol):

  • 即将出现总大小未知的大量数据。
  • 对于每个子数据包,消息都会显示“这是一个大小为 NN KB 的子数据包”。
  • 对于最后一个子数据包,大小可能会更短 - 这没关系,并且可能表示“大量数据结束”。
  • 如果最后一个子数据包是“完整大小”,您可以发送一个空的最后一个数据包来指示 EOS。
  • 或者,如果子数据包的大小可变,您始终可以发送显式 EOS 数据包。

还要考虑如果您不想使用命名管道,而希望升级系统以通过套接字连接到另一台计算机,那么将来会发生什么。

我认为您应该使用数据包来设计系统,其中数据包 header 包含数据的大小(大多数网络协议(protocol)(例如 TCP/IP)的工作方式)。如果存在未知大小的更高级别的数据流,请按照上面概述的方式进行处理。但即便如此,如果您能提前知道总体尺寸,那就更好了。

关于ipc - 数据包通过命名管道传输?单字节缓冲区还是预先确定大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2078053/

相关文章:

c - 在用户空间使用 netlink 从内核接收数据时出错

python - FIFO 管道中的数据丢失?

c - *nix : "echo ' start working' >/etc/. 示例”: how is this implemented?

c# - .NET 是否可以在进程之间共享大型内存中的集合?

c - 谁免费的 setvbuf 缓冲区?

vim - 显示当前缓冲区数

android - 在文件 flutter 中保存音频流/Uint8List 数据

c - 关于命名管道的简短阅读(matlab->linux)

java - 如何为CreateNamedPipe指定SECURITY_ATTRIBUTES?

perl - 制作一个运行24/7并从命名管道读取的Perl守护程序