在 linux 和 windows 中,send() 和 recv() 调用(通常用于 TCP,但我认为也可以与 UDP 一起使用)可能会提前返回,而不会发送您想要发送的全部数据。这将导致线程问题,因为您的消息将被拆分。
我发现使用以下属性包装 recv() 和 send() 函数是最简单的:
- 只有在我们请求的所有数据都写入套接字后才返回
- 线程安全
然后在我会使用发送/接收的所有地方使用包装器。
这是包装器的代码(随意更改错误处理):
//linux (must change SOCKET types to int)
//#include <sys/socket.h>
//windows
//#include <Winsock2.h>
//#include <ws2tcpip.h>
//blocks until the full amount of bytes requested are read
//thread safe
//throws exception on error
void recv_bytes(SOCKET socket, char* buf, int len, int flags){
static std::mutex mtx;
mtx.lock();
int bytes_received = 0;
while (bytes_received != len){
int bytes = recv(socket, buf + bytes_received, len - bytes_received, flags);
//error check
if (bytes == 0){
throw std::exception("Network Exception");
}
bytes_received += bytes;
}
mtx.unlock();
}
//blocks until the full amount of bytes requested are sent
//thread safe
//throws exception on error
void send_bytes(SOCKET socket, char* buf, int len, int flags){
static std::mutex mtx;
mtx.lock();
int bytes_sent = 0;
while (bytes_sent != len){
int bytes_s0 = send(socket, buf, len, flags);
if (bytes_sent == SOCKET_ERROR) {
mtx.unlock();
throw std::exception("Network Exception");
}
bytes_sent += bytes_s0;
}
mtx.unlock();
}