Действительно, как сказано в предыдущем ответе: «Самый безопасный механизм - передача данных в сокет только одному потоку».
Но если вы хотите, чтобы несколько потоков вызывали чтение / запись, вы должны сами гарантировать безопасность потоков. Я написал обертку вокруг send и recv ниже, которая сделает это за вас.
Send () и Recv () являются потокобезопасными в том смысле, что они не вызывают сбой, но нет гарантии, что данные не будут «смешаны» с данными, отправленными из других потоков. Поскольку мы, скорее всего, этого не хотим, мы должны блокировать, пока все данные потока не будут подтверждены, отправлены или получены, или по ошибке. Такой длительный блокирующий вызов может быть проблематичным, поэтому убедитесь, что вы делаете это в потоках, которые могут обрабатывать длинные блокирующие операции.
Для Linux:
#include <sys/types.h>
#include <sys/socket.h>
#include <map>
#include <mutex>
/* blocks until the full amount of bytes requested are read
* thread safe
* throws exception on error */
void recv_bytes(int sock, char* buf, int len, int flags){
static std::map<int, std::mutex> mtx;
std::lock_guard<std::mutex> lock(mtx[sock]);
int bytes_received = 0;
while (bytes_received != len){
int bytes = recv(sock, buf + bytes_received, len - bytes_received, flags);
//error check
if (bytes == -1){
throw std::runtime_error("Network Exception");
}
bytes_received += bytes;
}
}
/* blocks until the full amount of bytes requested are sent
* thread safe
* throws exception on error */
void send_bytes(int sock, char* buf, int len, int flags){
static std::map<int, std::mutex> mtx;
std::lock_guard<std::mutex> lock(mtx[sock]);
int bytes_sent = 0;
while (bytes_sent != len){
int bytes_s0 = send(sock, buf, len, flags);
if (bytes_sent == -1) {
throw std::runtime_error("Network Exception");
}
bytes_sent += bytes_s0;
}
}