第7章课后题7-6
设计两个程序,要求用消息队列实现聊天程序,每次发言后自动在发言内容后面增加系统时间。程序结束时增加结束字符,比如最后输入“88”后结束进程。
SERVER.C
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define SERVER_MSG 20
#define CLIENT_MSG 21
#define NAMESIZE 20
#define QUIT "88"
struct msgbuf{
long msg_type;
char msg_user[20];
char msg_time[30];
char msg_text[100];
};
int main(){
int qid;
char username[NAMESIZE];
key_t key;
int len, rfd;
fd_set read_set;
struct msgbuf msg;
struct timeval timeout;//这个是用来判断是否超时
time_t t;
if ((key=ftok(".",'a')) == -1){
printf("failed to make a standard key.\n");
exit(1);
}
if((qid=msgget(key,IPC_CREAT|0666)) == -1){
printf("failed to get message queue");
exit(1);
}
printf("给自己起个名字吧: ");
scanf("%s",username);
len = sizeof(msg.msg_text);
rfd = fileno(stdin);
fflush(stdin);
printf("----------\n");
fflush(stdout);
while(1){
if( msgrcv(qid, &msg, len,CLIENT_MSG,IPC_NOWAIT)>0 ){
//此处为了美观,我把时间写在了前面,交换一下后两个参数的位置即可
printf("%s : %s\n%s\n",msg.msg_user,msg.msg_time,msg.msg_text);
printf("----------\n");
fflush(stdout);
}
FD_ZERO(&read_set);
FD_SET(rfd, &read_set);
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
if(select(rfd+1, &read_set, NULL, NULL, &timeout) <= 0)
continue;
if(FD_ISSET(rfd, &read_set)){
fgets(msg.msg_text, len, stdin);
msg.msg_text[strlen(msg.msg_text) - 1]='\0';
if( strlen(msg.msg_text) == 0)
continue;
if( strcmp(QUIT, msg.msg_text) == 0){//输入QUIT 结束聊天
msgctl(qid,IPC_RMID,NULL);
break;
}
msg.msg_type = SERVER_MSG;
time(&t);
strcpy(msg.msg_time, ctime(&t));
strcpy(msg.msg_user, username);
msgsnd(qid, &msg, len, IPC_NOWAIT);
printf("----------\n");
fflush(stdout);
}
}
return 0;
}
~
CLIENT.C
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define SERVER_MSG 20
#define CLIENT_MSG 21
#define NAMESIZE 20
#define QUIT "88"
struct msgbuf{
long msg_type;
char msg_user[20];
char msg_time[30];
char msg_text[100];
};
int main(){
int qid;
char username[NAMESIZE];
key_t key;
int len, rfd;
fd_set read_set;
struct msgbuf msg;
struct timeval timeout;//这个是用来判断是否超时?
time_t t;
if ((key=ftok(".",'a')) == -1){
printf("failed to make a standard key.\n");
exit(1);
}
if((qid=msgget(key,IPC_CREAT|0666)) == -1){
printf("failed to get message queue");
exit(1);
}
printf("给自己起个名字吧: ");
scanf("%s",username);
len = sizeof(msg.msg_text);
rfd = fileno(stdin);
fflush(stdin);
printf("----------\n");
fflush(stdout);
while(1){
if( msgrcv(qid, &msg, len,SERVER_MSG,IPC_NOWAIT)>0 ){
//此处为了美观,我把时间写在了前面,交换一下后两个参数的位置即可
printf("%s : %s\n%s\n",msg.msg_user,msg.msg_time,msg.msg_text);
printf("----------\n");
fflush(stdout);
}
FD_ZERO(&read_set);
FD_SET(rfd, &read_set);
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
if(select(rfd+1, &read_set, NULL, NULL, &timeout) <= 0)
continue;
if(FD_ISSET(rfd, &read_set)){
fgets(msg.msg_text, len, stdin);
msg.msg_text[strlen(msg.msg_text) - 1]='\0';
if( strlen(msg.msg_text) == 0)
continue;
if( strcmp(QUIT, msg.msg_text) == 0){//输入QUIT 结束聊天
msgctl(qid,IPC_RMID,NULL);
break;
}
msg.msg_type = CLIENT_MSG;
time(&t);
strcpy(msg.msg_time, ctime(&t));
strcpy(msg.msg_user, username);
msgsnd(qid, &msg, len, IPC_NOWAIT);
printf("----------\n");
fflush(stdout);
}
}
return 0;
}
~
注意:结构体里的三个数组之和不要超过 512,不然在读取信息的时候会读不完整。
struct msgbuf{
long msg_type;
char msg_user[20];
char msg_time[30];
char msg_text[100];
};