无法使用结构来存储并稍后使用 recvfrom 打印 udp 数据
Unable to use a structure to store and later on print udp data usin recvfrom
我正在尝试使用以下结构将接收到的数据放入:
typedef struct packet {
uint8_t magic;
uint8_t version;
uint16_t body_length;
char *body;
} packet;
这是打印函数:
void displayPacket (struct packet p){
printf("Magic : %u\n",p.magic);
printf("Version : %u\n",p.version);
printf("Body Length: %d\n",ntohs(p.body_length));
printf("Body : %s\n",p.body);
}
在我的主要任务中,我正在尝试将接收到的数据保存在我的结构中:
unsigned char reply[1024];
struct packet reply_packet;
reply_packet.body = malloc(1021);
reply_packet.body[1020] = '[=12=]';
rc = recvfrom(s,&reply_packet,sizeof(reply_packet),0,NULL,NULL);
displayPacket(reply_packet);
free(reply_packet.body);
close(s);
输出:
Magic : 95
Version : 1
Body Length: 1008
[1] 4741 segmentation fault ./network
Magic、Version、Body Length 是数据包开头的预期输出。由于其他对等方遵循的协议,数据包的最大限制大小为 1024 字节。
但是,我有一个分段错误,由我的 displayPacket 函数引起,更准确地说是这一行:
printf("Body : %s\n",p.body);
如果有帮助的话,这是 valgrind 的输出:
==4886== Invalid read of size 1
==4886== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4886== by 0x4E994D2: vfprintf (vfprintf.c:1643)
==4886== by 0x4EA0F25: printf (printf.c:33)
==4886== by 0x108EFD: displayPacket (network.c:143)
==4886== by 0x1090FF: main (network.c:189)
==4886== Address 0x3030000000000000 is not stack'd, malloc'd or (recently) free'd
==4886==
==4886==
==4886== Process terminating with default action of signal 11 (SIGSEGV)
==4886== General Protection Fault
==4886== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4886== by 0x4E994D2: vfprintf (vfprintf.c:1643)
==4886== by 0x4EA0F25: printf (printf.c:33)
==4886== by 0x108EFD: displayPacket (network.c:143)
==4886== by 0x1090FF: main (network.c:189)
它已经困扰我好几个小时了,尽管它看起来很微不足道...
预期的输出将是数据包中其余内容的内容。到目前为止,我已经能够做到。
请问您认为解决这个问题的方案是什么?
谢谢。
编辑 1:
通过像这样修改结构解决了分段错误问题:
typedef struct packet {
uint8_t magic;
uint8_t version;
uint16_t body_length;
char body[1021];
} packet;
以及其余代码:
unsigned char reply[1024];
struct packet reply_packet;
reply_packet.body[1020] = '[=17=]';
rc = recvfrom(s,&reply_packet,sizeof(reply_packet),0,NULL,NULL);
printf("body[0] %d\n",reply_packet.body[0]);
displayPacket(reply_packet);
close(s);
displayPacket保持不变
packet.body 是一个指针。传递指针实际上没有意义,因为远程机器上数据的地址是无用的,而且您将始终只读取 body 的 sizeof(pointer) 字节。你可以这样做:
typedef struct packet {
uint8_t magic;
uint8_t version;
uint16_t body_length;
char body[MAX_BODY_SIZE];
} packet;
您正在 printf 中崩溃,因为您取消引用了一个错误的指针。即使 body 的长度可变,您也可以将 MAX_BODY_SIZE 设置为最大可能的大小,然后使用 body_length 字段计算出实际大小。
您也可以删除 reply 变量,因为它未被使用。
更新:你很接近。您正在将 body 打印为数字。既然你提到了 ASCII,我假设它是一个字符串。另外,需要根据body的实际长度NULL终止。这是您需要的:
struct packet reply_packet;
rc = recvfrom(s,&reply_packet,sizeof(reply_packet),0,NULL,NULL);
reply_packet.body[packet.body_length] = '[=11=]'; // null term after the body length
printf("body[0] %s\n",reply_packet.body); // change to %s and remove [0], you want the pointer not a character
displayPacket(reply_packet);
我正在尝试使用以下结构将接收到的数据放入:
typedef struct packet {
uint8_t magic;
uint8_t version;
uint16_t body_length;
char *body;
} packet;
这是打印函数:
void displayPacket (struct packet p){
printf("Magic : %u\n",p.magic);
printf("Version : %u\n",p.version);
printf("Body Length: %d\n",ntohs(p.body_length));
printf("Body : %s\n",p.body);
}
在我的主要任务中,我正在尝试将接收到的数据保存在我的结构中:
unsigned char reply[1024];
struct packet reply_packet;
reply_packet.body = malloc(1021);
reply_packet.body[1020] = '[=12=]';
rc = recvfrom(s,&reply_packet,sizeof(reply_packet),0,NULL,NULL);
displayPacket(reply_packet);
free(reply_packet.body);
close(s);
输出:
Magic : 95
Version : 1
Body Length: 1008
[1] 4741 segmentation fault ./network
Magic、Version、Body Length 是数据包开头的预期输出。由于其他对等方遵循的协议,数据包的最大限制大小为 1024 字节。
但是,我有一个分段错误,由我的 displayPacket 函数引起,更准确地说是这一行:
printf("Body : %s\n",p.body);
如果有帮助的话,这是 valgrind 的输出:
==4886== Invalid read of size 1
==4886== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4886== by 0x4E994D2: vfprintf (vfprintf.c:1643)
==4886== by 0x4EA0F25: printf (printf.c:33)
==4886== by 0x108EFD: displayPacket (network.c:143)
==4886== by 0x1090FF: main (network.c:189)
==4886== Address 0x3030000000000000 is not stack'd, malloc'd or (recently) free'd
==4886==
==4886==
==4886== Process terminating with default action of signal 11 (SIGSEGV)
==4886== General Protection Fault
==4886== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4886== by 0x4E994D2: vfprintf (vfprintf.c:1643)
==4886== by 0x4EA0F25: printf (printf.c:33)
==4886== by 0x108EFD: displayPacket (network.c:143)
==4886== by 0x1090FF: main (network.c:189)
它已经困扰我好几个小时了,尽管它看起来很微不足道...
预期的输出将是数据包中其余内容的内容。到目前为止,我已经能够做到。
请问您认为解决这个问题的方案是什么?
谢谢。
编辑 1:
通过像这样修改结构解决了分段错误问题:
typedef struct packet {
uint8_t magic;
uint8_t version;
uint16_t body_length;
char body[1021];
} packet;
以及其余代码:
unsigned char reply[1024];
struct packet reply_packet;
reply_packet.body[1020] = '[=17=]';
rc = recvfrom(s,&reply_packet,sizeof(reply_packet),0,NULL,NULL);
printf("body[0] %d\n",reply_packet.body[0]);
displayPacket(reply_packet);
close(s);
displayPacket保持不变
packet.body 是一个指针。传递指针实际上没有意义,因为远程机器上数据的地址是无用的,而且您将始终只读取 body 的 sizeof(pointer) 字节。你可以这样做:
typedef struct packet {
uint8_t magic;
uint8_t version;
uint16_t body_length;
char body[MAX_BODY_SIZE];
} packet;
您正在 printf 中崩溃,因为您取消引用了一个错误的指针。即使 body 的长度可变,您也可以将 MAX_BODY_SIZE 设置为最大可能的大小,然后使用 body_length 字段计算出实际大小。
您也可以删除 reply 变量,因为它未被使用。
更新:你很接近。您正在将 body 打印为数字。既然你提到了 ASCII,我假设它是一个字符串。另外,需要根据body的实际长度NULL终止。这是您需要的:
struct packet reply_packet;
rc = recvfrom(s,&reply_packet,sizeof(reply_packet),0,NULL,NULL);
reply_packet.body[packet.body_length] = '[=11=]'; // null term after the body length
printf("body[0] %s\n",reply_packet.body); // change to %s and remove [0], you want the pointer not a character
displayPacket(reply_packet);