如果有人在将来遇到这个问题,我会把它留下来。
*注意从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比较陌生,所以请原谅我的无知。我猜这真的很容易但是很有意思。
答案 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主机短)功能访问tm
和rid
。
答案 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"
。