我用 c 撰寫了一個程式,它創建一個子行程來接收訊息,父行程發送訊息。它不會從其父行程接收訊息,這是設計使然,也是我使用 MSG_EXCEPT 的原因。所以它打算讓程式運行 2 個實體,它們可以發送和接收訊息。問題是程式只發送一些訊息,而不是全部,我不知道為什么......
另外,我必須使用gcc -D_GNU_SOURCE chat.c -o chat編譯,否則它有一個關于MSG_EXCEPT. 有誰知道在不使用這些編譯器標志的情況下讓 MSG_EXCEPT 作業的更好方法嗎?代碼中的某些內容會更可取,以便它可以移植。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
typedef struct messageBuffer {
long type;
char text[256];
} MsgBuf;
typedef struct MessageStruct {
MsgBuf message;
int success;
} Message;
void handler(int sig){
_exit(0);
}
int open_queue( key_t keyval )
{
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0666 )) == -1)
{
return(-1);
}
return qid;
}
void SendMessage(int qid, int msgtype, char* msgtxt)
{
MsgBuf msg;
time_t t;
msg.type = msgtype;
snprintf(msg.text, sizeof(msg.text), "%s", msgtxt);
time(&t);
if(msgsnd(qid, (void*)&msg, sizeof(msg.text), IPC_NOWAIT) == -1)
{
perror("msgsnd error");
exit(EXIT_FAILURE);
}
}
Message ReceiveMessage(int qid, int msgtype)
{
Message msg;
msg.success = 1;
if(msgrcv(qid, (void*)&msg.message, sizeof(msg.message.text), msgtype, IPC_NOWAIT | MSG_NOERROR | MSG_EXCEPT) == -1)
{
if (errno != ENOMSG)
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
else
msg.success = 0;
}
return msg;
}
void ClearCurrentConsoleLine()
{
printf("\x1b[1F"); // Move to beginning of previous line
printf("\x1b[2K"); // Clear entire line
}
int main(void)
{
pid_t pid;
pid_t ppid = getpid();
int msgkey = 6666;
char str[256];
Message msg;
char* writemsg = "Write your message below:\n";
pid = fork();
int qid = open_queue(msgkey);
if(qid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
if(pid < 0)
{
perror("Forking error!");
abort();
}
else if(pid == 0)
{
signal(SIGCONT,handler);
while(1)
{
msg = ReceiveMessage(qid, ppid);
if(msg.success)
{
ClearCurrentConsoleLine();
printf("message: %ld: %s\n", msg.message.type, msg.message.text);
printf("%s", writemsg);
}
}
exit(0);
}
while(1)
{
printf("%s", writemsg);
fgets(str, sizeof(str), stdin);
int n = strlen(str);
if(str[n-1] == '\n')
str[n-1] = '\0';
ClearCurrentConsoleLine();
ClearCurrentConsoleLine();
printf("Me: %s\n", str);
if(strcmp(str, "exit") == 0)
{
printf("exiting\n");
break;
}
SendMessage(qid, ppid, str);
}
printf("Killing: %d\n", pid);
kill(pid,SIGCONT);
exit(0);
}
uj5u.com熱心網友回復:
MSG_EXCEPT 不應在這里使用,只需洗掉此標志
MSG_EXCEPT 與大于 0 的 msgtyp 一起使用以讀取訊息型別與 msgtyp 不同的佇列中的第一條訊息。
uj5u.com熱心網友回復:
原來那個特定的訊息佇列只是一個問題。所以我只是關閉了訊息佇列并開始了一個新的佇列并全部修復。關于 MSG_EXCEPT,我需要使用它,因為我不想只獲取當前佇列中的任何訊息,就像使用 0 一樣,我想獲取任何不是我自己提交的訊息,除了一個訊息之外的任何訊息用我用來發送它們的密鑰。我可以這樣做的另一種方法是每個行程有 2 個訊息佇列,一個用于獲取另一個聊天行程的密鑰和訊息佇列,另一個用于在另一個聊天行程之間發送訊息,但這會增加復雜性,這只是意味著成為一個簡單的實作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/326774.html
上一篇:與fork()共享記憶體
