Разрешены ли параллельные вызовы send/recv в одном и том же сокете? - программирование
Подтвердить что ты не робот

Разрешены ли параллельные вызовы send/recv в одном и том же сокете?

  • Можно ли вызывать отправку из одного потока и recv из другого в тот же сокет?
  • Можно ли вызывать несколько отправлений параллельно из разных потоков в одном и том же сокете?

Я знаю, что хороший дизайн должен избегать этого, но я не понимаю, как будут выглядеть эти системные API. Я тоже не могу найти хорошую документацию.

Полезны любые указатели в направлении.

4b9b3361

Ответ 1

POSIX определяет send/recv как атомные операции, поэтому, предполагая, что вы говорите о POSIX send/recv, тогда да, вы можете вызывать их одновременно из нескольких потоков, и все будет работать.

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

Если вы используете SOCK_STREAM сокеты, пытаясь сделать что-то параллельное, вряд ли будет полезно, поскольку send/recv может отправлять или получать только часть сообщения, что означает, что все может быть разделено.

Блокировка send/recv на SOCK_STREAM сокетах блокируется только до тех пор, пока они не отправят или не возвратят хотя бы 1 байт, поэтому разница между блокировкой и неблокировкой не является полезной.

Ответ 2

Дескриптор сокета относится к процессу, а не к определенному потоку. Следовательно, можно отправлять/получать в/из одного и того же сокета в разных потоках, ОС будет обрабатывать синхронизацию.

Однако, если порядок отправки/получения семантически значим, вы сами (соответственно ваш код) должны обеспечить правильное упорядочение между операциями в разных потоках - как это всегда происходит с потоками.

Ответ 3

Я не вижу, как получение параллельно может выполнить что угодно. Если у вас есть сообщение с 3 байтами, 1 поток может получить 1-й 2 байта, а другой - последний байт, но вы не сможете сказать, что именно. Если ваши сообщения не являются длинными байтами, вы не можете надежно сделать что-либо для работы с несколькими потоками.

Несколько отправлений могут работать, если вы отправили все сообщение за один раз, но я не уверен. Возможно, что можно перезаписать другой. Для этого не было бы никакой пользы от производительности.

Если вам нужно отправить несколько потоков, вам необходимо реализовать очередь синхронизированных сообщений. Имейте один поток, который выполняет фактическую отправку, которая считывает сообщения из очереди, и другие потоки выдают целые сообщения. То же самое будет работать для приема, но поток приема должен знать формат сообщений, чтобы он мог десериализовать их должным образом.