如何通过C中的套接字将两个缓冲区一起发送?

时间:2014-06-01 01:24:34

标签: c arrays sockets

我正在编写一个函数,用于通过套接字发送包含某些数据大小的标头,然后是数据本身。 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()。

1 个答案:

答案 0 :(得分:3)

您可以查看允许发送io-vector的writevsendmsg,提供分散/聚集的概念。
使用网络应用程序通常面临将一些缓冲区一起发送的情况(调整协议)。如果有许多小缓冲区(例如char,int,long元素,那么复制并不昂贵),我通常将它们聚合成一个大的缓冲区。如果你需要发送更大的缓冲区,使用scatter / gather更好,因为它确实需要进行内存复制(所以调用零拷贝)。
sendmsgwritev更高级,它接受一些TCP / IP选项。 此外,如果你的缓冲区是一个文件,你可以使用sendfile,它使用DMA来避免额外的内存复制。