C错误从流式套接字读取数据包
Posted
技术标签:
【中文标题】C错误从流式套接字读取数据包【英文标题】:C error reading packet from streaming socket 【发布时间】:2013-02-08 21:21:30 【问题描述】:我只是在 C 中使用流式套接字,但在读取从服务器应用程序返回的数据包时遇到问题。下面的代码显示了在客户端和服务器端使用的结构。
struct packet
uint16_t f1;
uint16_t f2;
uint32_t f3;
uint16_t pf1;
uint32_t pf2;
;
发送服务器端:
char buffer[14];
struct packet myPacket;
myPacket.f1 = 2321;
myPacket.f2 = 4423;
myPacket.f3 = 2134;
myPacket.pf1 = 765;
myPacket.pf2 = 9867;
htonPacket(myPacket, buffer);
将数据打包到缓冲区的函数。
void htonPacket(struct packet h, char buffer[14])
uint16_t u16;
uint32_t u32;
u16 = htons(h.f1);
memcpy(buffer+0, &u16, 2);
u16 = htons(h.f2);
memcpy(buffer+2, &u16, 2);
u32 = htonl(h.f3);
memcpy(buffer+4, &u32, 4);
u16 = htons(h.pf1);
memcpy(buffer+8, &u16, 2);
u32 = htonl(h.pf2);
memcpy(buffer+10, &u32, 4);
解包打印客户端:
void ntohPacket(struct packet* h, char buffer[14])
uint16_t u16;
uint32_t u32;
memcpy(&u16, buffer+0, 2);
h->f1 = ntohs(u16);
memcpy(&u16, buffer+2, 2);
h->f2 = ntohs(u16);
memcpy(&u32, buffer+4, 4);
h->f3 = ntohl(u32);
memcpy(&u16, buffer+6, 2);
h->pf1 = ntohs(u16);
memcpy(&u32, buffer+8, 4);
h->pf2 = ntohl(u32);
打印解压后的数据:
printf("myPacket.f1: %d\n", myPacket.f1);
printf("myPacket.f2: %d\n", myPacket.f2);
printf("myPacket.f3: %d\n", myPacket.f3);
printf("myPacket.pf1: %d\n", myPacket.pf1);
printf("myPacket.pf2: %d\n", myPacket.pf2);
当我打印这些值时,很明显我在寻址或写入错误的内存位置时遇到了一些问题,但我似乎找不到错误。
myPacket.f1: 2321
myPacket.f2: 4423
myPacket.f3: 2134
myPacket.pf1: 2134
myPacket.pf2: 50135040
【问题讨论】:
为什么所有的舞蹈都是从一个结构中复制东西到一个变量中,然后调整字节序和 memcpy?你可以一口气做dst->f1 = htons(src->f1)
。让struct
s 处理事情要容易得多,而不是胡乱处理单个字节(当然,您必须小心编译器不会偷偷填充)。我认为以这种方式重做代码将解决您的问题。
我正在学习,我只是在扩展我在数据包中找到的一个示例。感谢您的建议。
@vonbrand:将其发布为答案,您将获得我的 + 投票;)
【参考方案1】:
好吧,您在 memcpy
操作中使用了不同的偏移量,所以您当然会得到垃圾......
memcpy(buffer+0, &u16, 2);
memcpy(buffer+2, &u16, 2);
memcpy(buffer+4, &u32, 4);
memcpy(buffer+8, &u16, 2);
memcpy(buffer+10, &u32, 4);
对比
memcpy(&u16, buffer+0, 2);
memcpy(&u16, buffer+2, 2);
memcpy(&u32, buffer+4, 4);
memcpy(&u16, buffer+6, 2);
memcpy(&u32, buffer+8, 4);
ntohPacket
中的最后几行应该是
memcpy(&u16, buffer+8, 2);
h->pf1 = ntohs(u16);
memcpy(&u32, buffer+10, 4);
h->pf2 = ntohl(u32);
【讨论】:
哦,谢谢。然而,在更正之后,出现了更有趣的事情。现在最后一个值与我的预期略有不同。 myPacket.pf2: 9728 当我发送 9867 时。 我会按照@vonbrand 的建议(在他的评论中)做。维持所有这些指标,总有一天会给你带来难以言喻的痛苦。【参考方案2】:您的 memcpy 偏移量错误。固定:
memcpy(&u16, buffer+0, 2);
h->f1 = ntohs(u16);
memcpy(&u16, buffer+2, 2);
h->f2 = ntohs(u16);
memcpy(&u32, buffer+4, 4);
h->f3 = ntohl(u32);
memcpy(&u16, buffer+8, 2); <-- here
h->pf1 = ntohs(u16);
memcpy(&u32, buffer+10, 4); <-- here
h->pf2 = ntohl(u32);
【讨论】:
【参考方案3】:为什么所有的舞蹈都需要从一个结构复制东西到一个变量中,然后调整字节顺序和 memcpy?你可以一口气做dst->f1 = htons(src->f1)
。让struct
s 处理东西要容易得多,而不是胡乱处理单个字节(当然,你必须小心编译器不会偷偷填充)。我认为以这种方式重做您的代码将解决您的问题。
【讨论】:
以上是关于C错误从流式套接字读取数据包的主要内容,如果未能解决你的问题,请参考以下文章
C# Begin/EndReceive - 我如何读取大数据?