我正在编写一个函数,用于通过套接字发送包含某些数据大小的标头,然后是数据本身。 send()
接受一个指针和一个大小,并从该指针读取/发送。我想使用一个带有两个指针和两个大小的函数,并从第一个指针读取/发送,然后在它到达第一个指针的末尾时切换到第二个指针。这样,我就可以在有效载荷数据之前发送标题,而无需额外调用系统网络堆栈或复制内存。
这是我目前的功能。我必须使用额外的发送循环才能首先发送标头:
int send_size(int socket, uint8_t* buf, size_t len){
if (!buf) return INVALID_INPUT;
uint8_t header[4];
for (int i = 0; i<4; i++){ // Put size of data into 4-byte header, little endian.
header[i] = len%256;
len = len/256;
}
size_t bytesRemaining = len + 4;
size_t sent;
while (bytesRemaining > len){ // Send header.
sent = send(socket, header, bytesRemaining - len, SO_NOSIGPIPE);
if (sent==-1) return NETWORK_ERROR;
bytesRemaining -= sent;
}
while (bytesRemaining > len){ // Send payload.
sent = send(socket, buf, bytesRemaining, SO_NOSIGPIPE);
if (sent==-1) return NETWORK_ERROR;
bytesRemaining -= sent;
}
return NO_ERROR;
}
我宁愿有一个发送循环告诉我的系统将两个数组一起发送,所以我不必经常调用send()。
答案 0 :(得分:3)
您可以查看允许发送io-vector的writev
或sendmsg
,提供分散/聚集的概念。
使用网络应用程序通常面临将一些缓冲区一起发送的情况(调整协议)。如果有许多小缓冲区(例如char,int,long元素,那么复制并不昂贵),我通常将它们聚合成一个大的缓冲区。如果你需要发送更大的缓冲区,使用scatter / gather更好,因为它确实需要进行内存复制(所以调用零拷贝)。
sendmsg
比writev
更高级,它接受一些TCP / IP选项。
此外,如果你的缓冲区是一个文件,你可以使用sendfile
,它使用DMA来避免额外的内存复制。