Windows 在进程间通信管道中发送前两个字节字符时,是否会自动添加 EOL 作为签名?

Does Windows automatically add, as a signature, an EOL when sending the first two-byte characters in the interprocess communication pipe?

提问人:chckx592 提问时间:1/20/2023 最后编辑:chckx592 更新时间:2/3/2023 访问量:108

问:

我有一个关于通过 Windows 管道发送命令和数据的一般问题。似乎这个问题不会发生在Unix操作系统上。

这个问题不是针对我的应用程序,但为了说明目的,我将通过使用 gnuplot-iostreammatplotplusplus C++ 库的两个示例来解释我的问题。

Gnuplot-iostream

在我的应用程序中,我通过 gnuplot-iostreamgnuplot 交互,这是一个 C++ IO 流 API。

简而言之,gnuplot-iostream API 作为一个简单的头文件分发,其中包括与 boost-iostream 库的链接,以向 gnuplot 应用程序发送命令和数据。为此,API 在用户的 C++ 程序和 gnuplot 之间打开一个管道,并且通过一个非常薄的抽象层,用户能够通过管道发送命令和数据。

当将数据发送到 gnuplot 时,我注意到第一个数据点没有正确绘制。经过非常仔细的调查,我发现通过管道发送的数据的前两个字符被忽略了。

请考虑以下代码片段。

#include <vector>
#include "gnuplot-iostream.h"

std::vector<double> x = {-1.45809};
std::vector<double> y = {1.34003};
std::vector<double> z = {3.92172};

Gnuplot gp(stdout);
gp << "set view 90, 0\n";
gp << "set xlabel 'x'\n";
gp << "set ylabel 'y'\n";
gp << "set zlabel 'z'\n";
gp << "splot '-' with points\n";
gp.send1d(boost::make_tuple(x, y, z));

在绘制上面的图时,我注意到 gnuplot 收到了 x = 0.45809,这意味着“-1”已被截断。下面是我在屏幕上的图像证明。

The x-coordinate is wrong. Instead of x = -1.45809, the plot shows that x = 0.45809, showing that the "-1" has been truncated.

我认为这种截断是由于 Windows 在前两个字符的末尾添加了 EOL。下一个例子希望能澄清我的主张。请注意,此 bug 尚未正式报告,但 gnuplot-iostream 的作者报告了有关 Windows 用户的 iostream 的几个问题,这些问题尚未修复。

Maplotplusplus加号

Matplotplusplus 是另一个使用 C++ 绘制图形的 API,其接口与 Python 的 matplotlib 非常相似。此 API 不使用 Python 解释器,而是与作为后端应用程序的 gnuplot 进行通信。

我不会进入细节,但是在对源代码进行彻底调查后,碰巧没有错误,但是控制台在运行简单的“hello world”绘图程序时输出了以下警告消息。

gnuplot> se
           ^
         line 0: unrecognized option - see 'help set'.

gnuplot> t terminal wxt title "Figure 1" size 560,420 enhanced font "Sans,10"
         ^
         line 0: invalid command

对我来说,很明显 Windows 在前两个字符的末尾添加了一个不需要的“\n”。发送的所需命令应为:,但“set”的“se”已被截断。所以 Windows 发送了:而不是。顺便说一句,我不是唯一报告此错误的用户。set terminal wxt title "Figure 1" size 560,420 enhanced font "Sans,10"se\nt terminal wxt title "Figure 1" size 560,420 enhanced font "Sans,10"

我的问题如下。是否有可能由于 Windows 而解决这个烦人的问题?为什么这种无用的双字节签名是通过管道发送的?解决这个问题的一个简单技巧是在字符串中添加两个空格,并在发送实际数据之前发送一个虚拟签名命令,但这不是一个干净的解决方案。

您知道我应该朝哪个方向搜索来解决这个问题吗?是 boost 库问题还是 Windows 问题?使用 Unix 操作系统似乎没有这样的大惊小怪,因为管道结构很好地集成到操作系统中。在 Windows 的情况下,操作系统管道结构完全不同,这可能会导致不可靠的通信问题。

C++ Windows 管道 IOSTREAM

评论

4赞 user7860670 1/21/2023
“以下代码片段” - 您应该提供最小的可重现示例,其中包括此代码的实际输出(Gnuplot接收的数据)。“由于 Windows 在前两个字符的末尾添加了 EOL”——现在这是一个大胆的声明,我宁愿怀疑它由于流行为而被替换——在文本模式下使用时发生的东西相同。特别是因为 gnuplot-iostream 在内部使用文本模式下的 fstream\n\r\nstd::fstream
0赞 Luke 1/23/2023
需要一个可重复的例子,因为它对我来说很好用。

答:

0赞 chckx592 2/3/2023 #1

需要刷新输出流缓冲区。