在这里,我必须使用SysV消息队列发送和接收动态数据。
所以在结构领域我有动态内存分配char *
,因为它的大小可能会有所不同。
那么如何才能在接收方收到此类消息。
请告诉我如何使用邮件队列发送动态长度的数据。
我遇到问题,我在下面发布了我的代码。
send.c
/*filename : send.c
*To compile : gcc send.c -o send
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char *mtext;
};
int main(void)
{
struct my_msgbuf buf;
int msqid;
key_t key;
static int count = 0;
char temp[5];
int run = 1;
if ((key = ftok("send.c", 'B')) == -1) {
perror("ftok");
exit(1);
}
printf("send.c Key is = %d\n",key);
if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
printf("Enter lines of text, ^D to quit:\n");
buf.mtype = 1; /* we don't really care in this case */
int ret = -1;
while(run) {
count++;
buf.mtext = malloc(50);
strcpy(buf.mtext,"Hi hello test message here");
snprintf(temp, sizeof (temp), "%d",count);
strcat(buf.mtext,temp);
int len = strlen(buf.mtext);
/* ditch newline at end, if it exists */
if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
if (msgsnd(msqid, &buf, len+1, IPC_NOWAIT) == -1) /* +1 for '\0' */
perror("msgsnd");
if(count == 100)
run = 0;
usleep(1000000);
}
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(1);
}
return 0;
}
receive.c
/* filename : receive.c
* To compile : gcc receive.c -o receive
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char *mtext;
};
int main(void)
{
struct my_msgbuf buf;
int msqid;
key_t key;
if ((key = ftok("send.c", 'B')) == -1) { /* same key as send.c */
perror("ftok");
exit(1);
}
if ((msqid = msgget(key, 0644)) == -1) { /* connect to the queue */
perror("msgget");
exit(1);
}
printf("test: ready to receive messages, captain.\n");
for(;;) { /* receive never quits! */
buf.mtext = malloc(50);
if (msgrcv(msqid, &buf, 50, 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
printf("test: \"%s\"\n", buf.mtext);
}
return 0;
}
答案 0 :(得分:3)
解决问题的几种方法是:
'\0'
。 修改:如何使用msgsnd
和msgrcv
:
您对结构和msgsnd
的使用是错误的,因为函数期望整个消息是一个连续的内存区域。 this等示例使用包含普通字段的结构,或者使用固定长度字符串数组的this(在底部)。
您也可以发送结构大小为动态的动态数据。这里的技巧是使用一个小的固定大小的结构,并分配比所需更多的数据。
让我们重写部分示例发件人代码:
struct my_msgbuf {
long mtype; /* Message type, must be > 0 */
char mtext[1]; /* Some compilers allow `char mtext[0]` */
};
/* ... */
int count = 0;
while (count < 100) {
count++;
/* Put string in a temporary place */
char tmp[64];
snprintf(tmp, sizeof(tmp), "Hi hello test message here %d", count);
/* +1 for the terminating '\0' */
size_t msgsz = strlen(tmp) + 1;
/* Allocate structure, and memory for the string, in one go */
struct my_msgbuf *buf = malloc(sizeof(struct my_msgbuf) + msgsz);
/* Set up the message structure */
buf->mtype = 1;
memcpy(buf->mtext, tmp, msgsz);
/* And send the message */
msgsnd(msgid, buf, msgsz, IPC_NOWAIT);
/* Remember to free the allocated memory */
free(buf);
}
上面的代码处理动态字符串的发送,只要小于63个字符(临时字符串的大小减去1)。
不幸的是msgrcv
并不真正支持接收动态大小的数据。不使用MSG_NOERROR
标志,检查错误E2BIG
,然后使用realloc
获取更大的邮件缓冲区,可以帮助您。
收到这样的东西:
/* Should start with larger allocation, using small just for example */
size_t msgsz = 8;
struct my_msgbuf *buf = NULL;
for (;;) {
/* Allocate if `buf` is NULL, otherwise reallocate */
buf = realloc(buf, msgsz);
/* Receive message */
ssize_t rsz = msgrcv(msgid, buf, msgsz, 1, 0);
if (rsz == -1) {
if (errno == E2BIG)
msgsz += 8; /* Increase size to reallocate and try again */
else {
perror("msgrcv");
break;
}
} else {
/* Can use `buf->mtext` as a string, as it already is zero-terminated */
printf("Received message of length %d bytes: \"%s\""\n", rsz, buf->mtext);
break;
}
}
if (buf != NULL)
free(buf);
以上接收代码只接收一条消息。如果你希望它匹配发送大量消息的发送者,那么将接收代码放在一个函数中,然后循环调用它。
免责声明:此代码直接在浏览器中编写,只读取手册页。我还没有测试过。