1

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

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

4

4 回答 4

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终止的情况下扫描超过消息的末尾。a为 128的snprintf()调用结果为:MAXBUFLEN

"%hd %hd %c%122s"

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

于 2013-09-09T02:39:07.133 回答
0

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

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

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

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

于 2013-09-09T02:43:39.097 回答
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.
于 2013-09-09T02:05:00.613 回答
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,因为它不会将空格存储到您的消息中。
错误检查总是好事。建议进行额外的现场检查。


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

于 2013-09-09T16:06:48.863 回答