Нет причин, по которым вы должны синхронизировать вызовы с send
или recv
, если только один отправитель или получатель.Подумайте, не было ли двух потоков, пытающихся получить сообщение.Скажем, ради обсуждения, что сообщение client => server имеет длину 8 байтов, причем первые 4 байта являются командой, а вторые 4 байта являются идентификатором объекта некоторого вида:
Thread A: sock.recv(8) obtains first 4 bytes
Thread B: sock.recv(8) obtains second 4 bytes
Здесь ни одна ветка не заканчивается полным сообщением.Теперь, много раз, что не произойдет , вы получите целое 8-байтовое сообщение как единое целое.Но это не гарантируется, и когда сервер / сеть загружаются, а сетевые буферы ОС заполняются, и у вас несколько потоков, пытающихся получить доступ к ЦП, более вероятно, что это произойдет.(И это не только Python BTW; то же самое было бы верно для программы на C).
Так что, да, сокеты «поточнобезопасны» в том смысле, что ровно один recv
одного потока получит заданный байтданные и ничто не мешает двум потокам одновременно вызывать recv
.ОС не запутается в этом.Но в сокете TCP (SOCK_STREAM
) нет ничего, что могло бы гарантировать, что один «поток» получит все «сообщение» (любой длины больше одного байта).
Если у вас есть два потока, с одним только получением и одним только отправкой, то конкуренции не будет, и для поддержания согласованного потока данных не потребуется блокировка.
UDP-сокеты OTOH «ориентированы на сообщения», поэтому для них не существует такой же проблемы.Каждый send
или recv
доставляет неделимую дейтаграмму.Получающий поток не получит часть дейтаграммы.Он получает всю дейтаграмму или ничего (хотя дейтаграмма может быть усечена из-за недостатка места в буфере; но в этом случае остаток просто отбрасывается , а не доставляется следующему получающему потоку).