将char数组分解为结构

时间:2013-09-09 02:01:15

标签: c memcpy

如果有人在将来遇到这个问题,我会把它留下来。

*注意从C客户端到C服务器时,此方法不起作用。这只适用于Java客户端到C服务器。所以我不得不放弃这种方法。

好吧,我现在和C战斗的时间太长了。我将UDP的一些信息从java客户端传递给C服务器。我可以在那里获取信息,但我不确定如何将消息分解为存储到这样的结构中

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

我收到这样的消息 测试是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字节短路和一个字符后跟一个未知的消息长度)并将其存储在结构中的适当部分。消息被正确发送,我无法将其分解为我需要的信息。我正在尝试

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比较陌生,所以请原谅我的无知。我猜这真的很容易但是很有意思。

4 个答案:

答案 0 :(得分:0)

第一行应该是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.

答案 1 :(得分:0)

由于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() 128进行MAXBUFLEN调用的结果是:

"%hd %hd %c%122s"

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

答案 2 :(得分:0)

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

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

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

您还应该注意到,网络协议的字节顺序与x86和amd64体系结构的字节顺序不同,因此您可能会收到10752而不是42。 要解决此问题,您可以使用ntohs()(网络TO主机短)功能访问tmrid

答案 3 :(得分:0)

第一部分使用 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,因为它不会在您的邮件中存储空格 错误检查总是很好。建议进行额外的现场检查。


BTW:不清楚cM.op字段是应该被视为文本还是数字。 OP是否需要存储1或'1'?以上假定文字。或者,可以使用"%hd%hd%hhd%n"

相关问题