【问题标题】:Transmitting variable structure size with Berkeley socket over a TCP connection通过 TCP 连接使用 Berkeley 套接字传输可变结构大小
【发布时间】:2014-03-24 23:48:15
【问题描述】:

我在 C 中定义了以下结构,我想使用伯克利套接字通过 Linux 中客户端和服务器之间的 TCP 连接 发送它:

struct Argument{
int pid;
int length;
chat op;
char *data;
};

由于我有“char *data”,它是一个指针,可用于在本地发送机器中分配可变大小的数据,我必须在两次不同的时间将此结构发送到接收方。 第一次,我只发送固定变量,即前三个变量。然后在接收时,我分配一个长度大小的缓冲区来第二次接收数据部分。

所以我的问题是无论如何只能将此结构以可变数据字段大小发送到另一侧,而不是我在做什么的两倍?

if (write(peer_fd, (struct Argument*) arg, sizeof (struct Argument)) < 0)
{
    close(peer_fd);
    return -1;
}

非常感谢。

【问题讨论】:

  • 如果你在分配结构时知道data的大小,你可以使用长度为0的数组。
  • @Nick 如果您有完全合法的解决方案,为什么要使用 hack?
  • 只是扔在那里,OP 似乎想要一个块。此外,它们在我住的地方是完全合法的:)
  • @Nick 正确的做法是使用灵活的数组成员,0 长度数组是对某些编译器的扩展,我怀疑 c 标准对它们有什么积极的说法。
  • 你说得对,实际上我的意思是灵活的数组成员。我的错。

标签: c linux berkeley-sockets


【解决方案1】:

考虑使用分散-聚集读写技术。

readv writev

wtitev 允许您在一次调用中从多个缓冲区(固定大小的标头和字符数组)写入。您会产生单个系统调用的成本,内核中的套接字代码将数据组装到单个缓冲区中(如果可能),并进行单个网络调用。

【讨论】:

  • 我试过你的方法,但是接收端的问题,readv命令没有返回iov的长度。你需要手动设置,所以我回到了原来的问题。
  • 对。但是你的问题在某种程度上得到了解决。在写入方面,您只有一个系统调用和一个网络写入(而不是每个 2 个)。在阅读方面,您可以做两件事之一。要么读入一个大小为数组大小上限的缓冲区 - 这导致单次读取。或者读取一个标题,第二个读取数组 - 这是两个系统调用但一个网络调用。任何一个都是对原版的改进。
  • 您能否详细说明阅读部分?你能举个例子让我读两遍吗?谢谢。
  • 您必须先读取固定数据,以便在尝试读取之前获取可变数据的长度——除非您知道可变数据的大小有上限并且您可以为最大可能大小预先分配足够的空间。如果您有上限,则可以使用readv()。如果没有上限,则必须使用单独的 read() 调用。
  • 这 2 次读取与您现在所做的类似。第一次读取会为您提供固定大小的标题,其中包含长度。第二次读取为您获取数组(此时您已分配正确大小的缓冲区)。这仍然是 2 个读取系统调用。但是只有一个网络读取。您不必为此使用 readv 。正常阅读就可以了。写入端将使用 writev。
猜你喜欢
  • 2011-09-18
  • 2023-04-08
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
相关资源
最近更新 更多