#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 Да, это обычно требуется. Это распространенная проблема бинарных протоколов связи. Как вы заметили, есть два способа обойти это: указать заголовок с длиной в начале каждого сообщения или иметь однозначно идентифицируемый маркер конца сообщения.