0

我目前正在尝试将处理数据报(udp)数据包的 ac 程序移植到一些更高级别的语言。由于数据包可以是可变大小的,它们以一个整数开始,说明它们的大小。在 c 中,我使用 MSG_PEEK 标志调用 recv 以首先仅接收此值,然后分配一个合适的缓冲区并读取数据包的其余部分。代码(简化)如下所示:

// Simplified message format.
struct message {
    int length;
    char[] text;
}
struct message *m = malloc (sizeof(int));

// Read out in just length.
recv (sock, m, sizeof(int), MSG_WAITALL | MSG_PEEK);
int txtlen = ntohl (m->length) * sizeof(char);
int msglen = sizeof(int) + txtlen;

// Read complete packet.
m = realloc (m, msglen);
read (sock, m, msglen);
m->text[txtlen] = '\0';

// Show result.
printf("%s\n", &m->text);

我想避免看似普遍的做法来分配一个巨大的缓冲区,并希望不会有更大的数据包到达。那么在 python 或 java 等高级语言中,是否可以预先查看数据报或确定其完整长度?

4

3 回答 3

1

我想避免看似常见的做法来分配一个巨大的缓冲区,并希望数据包不会变得更大。

不知道你是什么意思。一个 UDP 数据包同时到达,所以初始整数告诉你缓冲区应该有多大;它到达后不会“增长”。

由于您要附加一个空字符,因此您需要在长度计算中考虑到这一点:

int msglen = sizeof(int) + txtlen + 1;

使用时要小心realloc()

m = realloc (m, msglen);

如果realloc失败,它将设置m为空。这意味着您将失去对最初分配给它的内存的唯一引用,因此您将永远无法获得free()它。尝试这样的事情:

void *tmp = realloc(m, msglen)
if (tmp == null) {
  // handle the error
}
m = tmp;

当您打印数据时,m->text计算为第一个字符的地址,因此您可以使用

printf("%s\n", m->text);

或者,您可以定义具有固定大小的结构,如

struct message {
  int length;
  char *text;
}

然后您可以使用malloc()(仅)分配您的文本缓冲区:

struct message m;
recv(sock, &m.length, sizeof(int), MSG_WAITALL | MSG_PEEK);
m.text = malloc(m.length + 1); // +1 for the null that you'll append
read(sock, m.text, m.length);
m.text(m.length) = '\0';

printf("%s\n", m.text);
free(m.text);

祝你的项目好运——网络编程总是一种学习体验!

于 2011-10-28T12:14:44.640 回答
0

为什么不这样做?

message = (struct message *)malloc(sizeof(struct message));
read(sock, &message->length, sizeof(int);
message->length = ntohl(message->length);
message->text = (char *)malloc(message->length + 1);
read(sock, message->text, message->length);
message->text[message->length] = 0;
于 2011-10-28T11:56:55.877 回答
0

UDP 数据报限制为 64K,然后以太网帧为 1500 字节(除非您的网络使用巨型帧,最多可达 9000 字节)。协议设计者通常会尽量避免IP 分段,因此您的传入数据包很可能很小,即小于 1500 字节。

我将从 1472 的静态缓冲区开始(1500 以太网帧长度 - 20 字节的 IP 标头 - 8 字节的 UDP 标头)。如果您必须处理一些任意协议 - 将其提高到 64K。如果您负担不起 - 使用 收集实际尺寸MSG_PEEK,找到一些方便的平均值,然后使用 设置备用计划malloc(3)

于 2011-10-28T12:44:02.583 回答