C: Чтение из символьной трубы AND int одновременно (хитрый) - PullRequest
0 голосов
/ 11 апреля 2019

Я пишу в трубе несколько целых чисел, и когда я заканчиваю, я пишу "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 ]

1 голос
/ 11 апреля 2019

Канал - это просто поток байтов, даже если вы правильно интерпретировали прочитанные байты как 16-битное целое число и как двухсимвольную строку «11», которая в ASCII является байтами 31 31, тогда как вы скажете «11»кроме целого 12593?Они имеют одинаковое двоичное представление.

Один из вариантов - просто продолжать чтение, пока канал не будет завершен, это может быть, скажем, подходящим для передачи файла.Но не разрешает отправлять туда и обратно сообщения.

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;
    }
}

Вы можете посмотреть на некоторые существующие протоколы о том, как они кодируют разные вещи в поток байтов.

0 голосов
/ 11 апреля 2019

Я не могу придумать какие-либо решения для одновременного чтения в конвейере для int и char

Нет решения этой проблемы per se , потому что из канала не читаются ни символы, ни целые числа, а скорее необработанные байты. Все остальное о том, как байты интерпретируются .

(я знаю, что работает на основе метода 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 и последующей интерпретации результата как двухбайтовое целое число.

...