C:同时从管道char和int读取(错位一个)

时间:2019-04-11 16:12:26

标签: c char int pipe

我正在管道中写入一些整数,结束时我写“ 11”。然后,当我从同一管道读取数据时,我必须取整数并对其进行处理,当我得到“ 11”时,我应该终止。但是我无法考虑可以在管道中同时读取int和char的任何解决方案(我知道这是基于fifo方法工作的。)

有什么想法吗?

//THIS IS AN EXAMPLE CODE OF WHAT I WANT TO DO 

//I am writing to the pipe
while(CONDITION)
    write(mypipe, &random_int, sizeof(short));
write(mypipe, "1", sizeof("11"));

/* code... */

//I am reading from the pipe
while(TRUE){
    read(mypipe, &received_int, sizeof(short));
    // if strcmp(receiver_int, "11")==0 then exit;
    // else do stuff with receiver_int
}

2 个答案:

答案 0 :(得分:1)

即使您将读取的字节正确地解释为16位整数和2字符串“ 11”(ASCII中为字节31 31),管道也只是字节流,那么如何分辨“除整数12593外还有11英寸?它们具有相同的二进制表示形式。

一个选择是保持读取直到管道终止,这可能适合传输文件。但是不允许持续的来回消息。

write(mypipe, &random_int, sizeof(short));
close(mypipe); // finished writing

// recv
while (true)
{
    short received_int;
    if (read(mypipe, &received_int, sizeof(short)) == sizeof(short)) // Not handling the int getting split into two separate read's here
    {
        // Use received_int
    }
    else return; // 0 on close
}

这就是为什么大多数协议在流(文本或二进制)顶部引入消息概念的原因。例如,您可能有一个8位的“操作码”,并说0是“断开连接”,而1是“带有整数的消息”,那么写一个整数:

 unsigned char opcode = 1;
 short random_int = 55; // Make sure it actually a short, as you used sizeof(short)!
 write(mypipe, &opcode, 1);
 write(mypipe, &random_int, sizeof(short));

要阅读,请先阅读操作码,然后再决定:

char opcode;
read(mypipe, &opcode, 1); // CHECK RETURN!
switch (opcode)
{
case 0: return; // Finished
case 1:
    {
        short received_int;
        read(mypipe, &received_int, sizeof(short)); // CHECK RETURN!
        // Use received_int
        break;
    }
}

您可能会查看一些现有协议,了解它们如何将不同的事物编码到字节流中。

答案 1 :(得分:0)

  

我想说什么解决方案,可以在管道中同时读取int和char

对于本身来说,没有任何解决方案,因为一个人从管道中既不读取字符也不读取整数,而是读取原始字节。其他所有内容都是关于字节如何解释

  

(我知道这是根据fifo方法工作的。)

FIFO具有与管道完全相同的约束。

通常来说,如果要跨任何个通信介质传递不同类型的对象,则需要某种格式或协议,以使接收者能够将数据解释为发送者想要的。范围从非常简单到非常复杂。您所描述的是一个特别简单的协议(实际上非​​常简单):数据由字节对组成,每个对都解释为无符号整数的字节,只是有一个特殊的两字节标记数据结束的顺序。

对于这样的协议,我可以这样写接收方:

union {
    uint16_t num;
    char s[3];    // Three bytes, not two, to allow for a terminator
} buffer = { .s = { 0 }};

while (1){
    read(mypipe, &buffer, sizeof(uint16_t));
    if (strcmp(buffer.s, "11") == 0) {
        break;
    }
    // do stuff with buffer.num ...
}

但是不,您所描述的协议没有提供一种方法来区分"11"的两个字节和用作整数值的两个相同的字节。结果,存在一个不能通过此协议发送的整数值。很有可能是12593(十进制),这是由于将"11"的字符编码为ASCII,然后将结果重新解释为两个字节的整数而产生的。