【Linux程序设计第三版】利用消息队列实现聊天程序

第7章课后题7-6

设计两个程序,要求用消息队列实现聊天程序,每次发言后自动在发言内容后面增加系统时间。程序结束时增加结束字符,比如最后输入“88”后结束进程。

SERVER.C

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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];
};

你可能感兴趣的:(作业,linux,c语言)