繁体   English   中英

将一个char数组分解为一个结构

[英]breaking up a char array into a structure

万一将来有人遇到这个问题,我会保留。

*注意:从C客户端到C服务器时,这种方法行不通。 这只能与Java客户端到C服务器一起使用。 所以我不得不放弃这种方法。

好的,我和C战斗已经很久了。 我正在将UDP的一些信息从Java客户端传递到C服务器。 我可以在那里获取信息,但是我不确定如何将消息分解成这样的结构

struct __attribute__((__packed__)) clientMessage
{
  short tml; 
  short rid;  
  char op;        
  char message[MAXBUFLEN-5];
};

我收到这样的消息,其中test是char test[MAXBUFLEN-5];

if ((numbytes = recvfrom(sockfd, test, MAXBUFLEN-1, 0,
  (struct sockaddr *)&their_addr, &addr_len)) == -1) {
     perror("recvfrom");
     exit(1);}

因此,我需要接收消息“ 7 2 1Yo”(两个2字节的短裤和一个char,后跟一个未知的消息长度),并将其存储到结构中的适当部分中。 消息已正确发送,我只是无法将其分解为所需的信息。 我目前正在尝试

memcpy(&cm.rid, &test, 2);
memcpy(&cm.tml, &test[1], 2);
memcpy(&cm.op, &test[4], 1);
memcpy(&cm.message, &test[5], MAXBUFLEN-5);

但是我的结果最终还是

Message: Yo
OP: 1Yo
RID: 7 1Yo
TML: 2 7 1Yo

它应该是

Message: Yo
OP: 1
RID: 2
TML: 7

我成功地收到了消息,但没有别的。 我是C的新手,请原谅我的无知。 我猜这真的很容易,但idk。

第一行应该是memcpy(&cm.rid, &test[0], 2); ,因为该地址应该是第一个字节的地址。

其余的:

memcpy(&cm.tml, &test[2], 2); // you want to get the third and forth byte, begin with index 2.
memcpy(&cm.op, &test[4], 1);  // the fifth byte, begin with index 4.
memcpy(&cm.message, &test[5], MAXBUFLEN-5); // the rest bytes.

由于test包含字符串"7 2 1Yo" ,因此您必须将字符串解析为所需的值。 您可以使用sscanf()完成此操作:

char fmt[256];
snprintf(fmt, sizeof(fmt), "%%hd %%hd %%c%%%ds", MAXBUFLEN-5-1);
sscanf(test, fmt, &cm.rid, &cm.tml, &cm.op, cm.message);

在上面的代码片段中,我们为解析创建了一个格式字符串。 这是必要的,以防止sscanf()在未\\0终止的情况下扫描超过消息的末尾。 snprintf()调用结果为MAXBUFLEN为128:

"%hd %hd %c%122s"

它告诉sscanf()扫描两个短十进制数字,一个char和一个不超过122个字符的字符串。

如果使用二进制协议,则在clientMessage的声明中最好使用例如int16_t而不是short,因为在c标准中未指定short的大小。

要访问存储在test的消息,您可以执行以下操作:

struct clientMessage *cm = (struct clientMessage *) test;

您还应该注意,网络协议的字节序不同于x86和amd64架构的字节序,因此您可能会收到10752而不是42的字节序。要解决此问题,您可以使用ntohs() (Network TO Host Short)函数来解决此问题。进入tmrid

第一部分使用sscanf() ,文本使用memcpy()

const char *message = "7 2 1Yo";
struct clientMessag cM;  
int offset = 0;
int n;
n = sscanf(message, "%hd %hd %c%n", &cM.tml, &cM.rid, &cM.op, &offset);
size_t SuffixLength = strlen(&message[offset]);
if ((n != 3) || (SuffixLength >= sizeof(cM.message))) {
  exit(1);  // handle syntax error;
}
memcpy(cM.message, &message[offset], SuffixLength + 1);
// Additional field checks like IsOKOpCode(cM.op)

我避免使用%s因为它不会在您的消息中存储空格。
错误检查始终是一件好事。 建议进行其他现场检查。


顺便说一句:尚不清楚cM.op字段视为文本还是数字。 OP是否要存储1或“ 1”? 以上假设文字。 或者,可以使用"%hd%hd%hhd%n"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM