【问题标题】:How can I send two buffers together through a socket in C?如何通过 C 中的套接字将两个缓冲区一起发送?
【发布时间】:2014-06-01 10:37:58
【问题描述】:

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

【问题讨论】:

  • 您需要创建由 2 个原始数组组成的第三个数组并发送它

标签: c arrays sockets


【解决方案1】:

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

【讨论】:

  • 这个答案是正确的,并且正是 OP 所需要的,但我很犹豫是否要在没有更多实质内容的情况下对其进行投票。
  • 是的,writev 正是我想要的。 linux.die.net/man/2/writev 的手册页有一个很好的例子。
猜你喜欢
  • 2010-11-09
  • 1970-01-01
  • 2013-02-16
  • 2014-08-19
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 2017-08-26
  • 2018-11-08
相关资源
最近更新 更多