Как уведомить основной поток через канал, если дочерний поток блокируется при чтении сокета?

#c #multithreading #sockets #pipe

Вопрос:

Описание моей ситуации и некоторый код

У меня есть основной поток, обрабатывающий события в цикле, и дочерний поток, ожидающий данных в сокете.

Дочерний поток блокируется во время ожидания ввода через сокет:

int n = read(socket, buffer, sizeof(buffer));

Полученные данные записываются во временный буфер размером 1024, а затем добавляются в глобальный буфер для дальнейшей обработки в основном потоке.

При поступлении входных данных дочерний поток уведомляет основной поток по каналу:

write(pipe-write-file-descriptor, some-id, sizeof(int));

Основной поток получает уведомление по каналу:

int n = read(pipe-read-file-descriptor, some-id, sizeof(int));

Затем основной поток может обрабатывать данные глобального буфера.

Возможные сценарии

Сценарий 1 с полученными байтами Дочерний поток вызывает «чтение из сокета», а затем «запись в канал», чтобы уведомить основной поток.

Сценарий 2 с полученными байтами > 1024: Необходим цикл, позволяющий дочернему потоку считывать все данные (временный буфер, заполненный 1024 байтами несколько раз, а затем добавленный в глобальный буфер назначения), и только после этого вызывать «запись в канал», чтобы уведомить основной поток.

Сценарий 3 с полученными байтами == 1024: Буфер заполняется один раз полностью, затем следующий цикл цикла ожидает новых данных в сокете. Но из-за блокировки сокета для чтения и отсутствия дополнительных входных данных (уже получено 1024 байта) дочерний поток БОЛЬШЕ НЕ МОЖЕТ УВЕДОМЛЯТЬ основной поток по каналу.

Как решить или обойти эту ситуацию в сценарии 3?

Комментарии:

1. Почему вы не можете изменить условие для случая 1 на received <= 1024 ?

2. Когда вы говорите «получено байтов == 1024», если счетчик байтов инициализирован 0, надеюсь, вы считаете до 1023 в своем коде

3. @Вики, конечно, я использую 0..1023 в качестве индекса. Но максимальное количество-1024.

4. Откуда вы знаете, сколько там данных? Вы должны знать, сколько байтов вам нужно прочитать, прежде чем уведомлять другой поток. Или вы ждете, пока сокет не будет закрыт с удаленного конца (что также приведет к прекращению чтения).

5. @ChristianHeller Да, это обычно требуется. Это распространенная проблема бинарных протоколов связи. Как вы заметили, есть два способа обойти это: указать заголовок с длиной в начале каждого сообщения или иметь однозначно идентифицируемый маркер конца сообщения.