[英]Want to Receive dynamic length data from a message queue in IPC?
在這里,我必須使用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'
。 編輯:如何使用msgsnd
和msgrcv
:
您對結構和msgsnd
是錯誤的,因為該函數期望整個消息是一個連續的內存區域。 實施例如本使用與正常字段的結構中,或者像這樣 (在底部),其使用固定長度字符串數組。
您也可以發送結構大小為動態的動態數據。 這里的技巧是使用一個小的固定大小的結構,並分配比所需更多的數據。
讓我們重寫部分示例發件人代碼:
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);
上面的接收代碼只接收一條消息。 如果您希望它與發送大量消息的發送方匹配,則將接收代碼放入函數中,並在循環中調用它。
免責聲明:此代碼直接在瀏覽器中編寫,只讀取手冊頁。 我沒有測試過。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.