C Unix msgsnd 不发送一些消息
C Unix msgsnd not sending some messages
我用 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] = '[=10=]';
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);
}
这里不要用MSG_EXCEPT
,去掉这个flag就可以了
MSG_EXCEPT
Used with msgtyp greater than 0 to read the first message
in the queue with message type that differs from msgtyp.
原来只是那个特定的消息队列有问题。所以我只是关闭了消息队列并开始了一个新的队列并且全部修复了。关于 MSG_EXCEPT,我需要使用它,因为我不想只获取队列中当前的任何消息,就像使用 0 一样,我想获取任何不是由我自己提交的消息,除了我用来发送它们的密钥之外的任何消息。我可以这样做的另一种方法是每个进程有 2 个消息队列,一个用于获取另一个聊天进程的密钥和消息队列,一个用于在另一个聊天进程之间发送消息,但这会增加复杂性,这只是意味着成为一个简单的实现。
我用 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] = '[=10=]';
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);
}
MSG_EXCEPT
,去掉这个flag就可以了
MSG_EXCEPT Used with msgtyp greater than 0 to read the first message in the queue with message type that differs from msgtyp.
原来只是那个特定的消息队列有问题。所以我只是关闭了消息队列并开始了一个新的队列并且全部修复了。关于 MSG_EXCEPT,我需要使用它,因为我不想只获取队列中当前的任何消息,就像使用 0 一样,我想获取任何不是由我自己提交的消息,除了我用来发送它们的密钥之外的任何消息。我可以这样做的另一种方法是每个进程有 2 个消息队列,一个用于获取另一个聊天进程的密钥和消息队列,一个用于在另一个聊天进程之间发送消息,但这会增加复杂性,这只是意味着成为一个简单的实现。