[英]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)函数来解决此问题。进入tm
和rid
。
第一部分使用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.