Допустимы ли параллельные вызовы для отправки / recv на одном сокете?


  1. можем ли мы вызвать send из одного потока и recv из другого на том же сокете?
  2. можем ли мы вызвать несколько отправок параллельно из разных потоков на одном сокете?

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

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

3 105

3 ответа:

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

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

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

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

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

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

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

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

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