C 从管道(FIFO)读取数据,然后比较字符串

C 从管道(FIFO)读取数据,然后比较字符串,c,linux,named-pipes,C,Linux,Named Pipes,我在用烟斗看书 char buf[255]; while((nbytes = read(fd,buf,sizeof(buf)) > 0)) // fd is the opened pipe { if(strcmp(buf,"IN")==0){ printf("%s\n", "SET IN"); } if(strcmp(buf,"OUT")==0){ printf(

我在用烟斗看书

char buf[255];

while((nbytes = read(fd,buf,sizeof(buf)) > 0)) // fd is the opened pipe
        {

          if(strcmp(buf,"IN")==0){
            printf("%s\n", "SET IN");
          }
          if(strcmp(buf,"OUT")==0){
            printf("%s\n", "SET OUT");
          }
}
现在,当我通过终端向管道写入数据时

echo "OUT" > /path/to/FIFO
我得到的结果是:“开始”


我键入的所有内容都会以“SET IN”作为输出。如何将其与从管道读取的字符串进行比较?

您将读取的数据视为字符串(通过将其传递到strcmp()),但无法保证输入数据以0结尾。特别是,
read()
不会0-终止数据,如果可能,它会用数据填充整个缓冲区

您需要自己完成,将read调用修改为:

while((nbytes = read(fd, buf, sizeof buf - 1)) > 0 ) // fd is the opened pipe
{
  buf[nbytes - 1] = '\0';
请注意,传递给
read()
的大小已经缩小,以便为终止符留出空间,我们添加了它

还请注意,我在时更正了
中的括号,正如上面@AhmedMasud的评论中提到的那样。这是一个很好的观点,我忘记强调了


更新:如所述,数据将以不可预测的块交付,因此协议可能很有用。对于在管道上流动的文本数据,最简单的协议是(当然?)基于行的。这意味着您应该收集数据,直到检测到行尾字符为止。当您这样做时,解析缓冲区的内容,然后清除它。

正如unwind所指出的,您不能直接将管道中的数据视为字符串数据并期望一切顺利

您真正需要做的是为您的数据传输定义一个协议,并编写一些可以发送和接收该协议的内容

不过,它不必很复杂

例如,您可以执行以下操作:前4个字节表示要发送的数据的长度,后跟数据。当您读取了4个字节+前4个字节的数据值时,您会将该数据与一组已知的预期值进行比较。如果您想使用字符串比较函数,部分数据可能包含空终止符。您也可以选择使用memcmp()执行测试,而不使用null终止


发送数据的方式有很多种,虽然这可能感觉有些过火,但你必须小心,不要假设当你打一个电话来读取数据时,你总能得到你想要的所有数据。在上面的示例中,您会一直调用它,直到获得预期的数据量,可能会对它进行缓冲,直到您拥有了所有数据,然后检查它是什么

顺便说一句:while中的条件也很奇怪,它将设置n字节因为你的括号是关闭的。应该是
while((nbytes=read(fd,buf,sizeof(buf)-1))>0{…}
非常感谢您的回答。@Defyleiti不客气。如果您觉得它有帮助,请考虑点击“接受”复选标记。谢谢。这真的不是个好主意。不能保证你会一次从管道中读取一大块数据,你可能会在预期字符串的中间终止。虽然这在这个人为的例子中可能不太可能,但我认为总体而言,这不是一个好的通用建议。我会写另一个更一般的答案。unwind所说的对这个例子可能永远有效。。但如果你开始用更大的信息做更复杂的事情,请记住这个答案:)