C言語は四つのウィンドウでチャットすることを実現します。


C言語は四つの窓口でチャットすることを実現します。
前の時間に勉強した共有メモリ、パイプ、メッセージキューなどのプロセス同期機構を練習するために、チャットのミニプロジェクトを作った。
プロジェクトの説明:
4つのプロセスがあります。AプロセスとBプロセスは通信を担当しています。標準入力から読み取った文字列はパイプを通して相手に送ります。A 1プロセスとB 1プロセスは表示を担当しています。
  • AプロセスとBプロセスはパイプを介して通信し、AプロセスとA 1プロセスは共有メモリを介して通信し、BプロセスとB 1プロセスはメッセージキューを介して通信する。
  • Aプロセスは標準から読んだ文字列を入力した後、パイプと共有メモリに入れて、パイプから読んだ文字列を共有メモリに入れます。BプロセスはパイプからAの並べた文字列を受け取ります。A 1プロセスは共有メモリに文字列を取り、スクリーンに印刷します。
  • Bプロセスは、標準から入力された文字列からAプロセスに送られ、同時にメッセージキューを介してB 1プロセスに送られ、B 1プロセスはメッセージキューからメッセージを読み出して、スクリーンに印刷される。
  • が終了すると、AとBのいずれかのプロセスにCrtl+cまたはCtrl+\を入力し、4つのプロセスはすべてのパイプ、共有メモリ、メッセージキューなどのリソースを削除し、その後、順序よく終了します。
  • オペレーティングシステム:Ubuntu 20.4
    言語:c
    コンパイラ:gcc
    func.h
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <time.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <sys/select.h>
    #include <sys/shm.h>
    #include <sys/sem.h>
    #include <sys/msg.h>
    #include <signal.h>
    
    #define ARGS_CHECK(argc, num){if(argc!=num){fprintf(stderr,"args error!
    "); return -1;}} #define ERROR_CHECK(ret,num,msg){if(ret == num){perror(msg); return -1;}}
    a.
    
    //========= A   ===========
    //1.         ,         B  
    //2.   B         
    //3.          ,  B       A1
    //===========================
    
    #include <func.h>
    
    int chatA(int shmid, int semid, char *p);
    int sndToA1(int semid, int shmid, char *p, char *msg);//          A1
    void closeAll();//         ,           
    void sigFunc(int signum);//  2  3       ,   A    2  3      close  
    
    //    ,                
    int semid;
    int shmid;//    
    char *p;
    
    int fdWrite;
    int fdRead;
    
    int main()
    {
        //1.      ,              ,     
        semid = semget(2000, 1, IPC_CREAT|0666);
        ERROR_CHECK(semid, -1, "A semget");
        shmid = shmget(1000, 4096, IPC_CREAT|0666);//        
        ERROR_CHECK(shmid, -1, "shmget");
        p = (char *)shmat(shmid, NULL, 0);
    
        signal(SIGINT, sigFunc);
        signal(SIGQUIT, sigFunc);
    
        int ret = chatA(shmid, semid, p);
        ERROR_CHECK(ret, -1, "run A");//            
        return 0;
    }
    
    int chatA(int shmid, int semid, char *p){
        //      1,    -1
        fdRead = open("1.pipe", O_RDONLY);//         1
        ERROR_CHECK(fdRead, -1, "open fdRead");//        
        fdWrite = open("2.pipe", O_WRONLY);//         2
        ERROR_CHECK(fdWrite, -1, "open fdWrite");//  
        setbuf(stdin, NULL);
        puts("=========== A ===========");
        char buf[512] = {0};
        fd_set rdset;//      ,            
        while(1){
            struct timeval timeout;//    
            timeout.tv_sec = 5;
            timeout.tv_usec = 15000000;//  5            
            FD_ZERO(&rdset);//     ,    
            FD_SET(fdRead, &rdset);//       1      
            FD_SET(STDIN_FILENO, &rdset);//               
            int tret = select(fdRead + 1,&rdset,NULL,NULL,&timeout);//  select    
            if(tret == 0){
                puts("time out!");
            }
            //select    ,    FD  ,    
            //    ,      
            if(FD_ISSET(fdRead, &rdset)){
                //       ,        ,   A1
                memset(buf, 0, sizeof(buf));//  buf    ,          
                int ret = read(fdRead, buf, 1024);//           
                if(ret == 0){
                    //              ,    
                    sigFunc(2);
                    break;
                }
                //   B       
                int type = 0;
                sscanf(buf, "%*d %d", &type);//       ,1    ,2        
                int snd_ret = 0;
                
                switch (type){
                case 1:
                    //   1   ,              A1
                    snd_ret = sndToA1(shmid, semid, p, buf);
                    ERROR_CHECK(snd_ret, -1, "sndToA1");
                    break;
                case 2:
                    //=====    B    2   ,      =====
                    // A1      2   , A1    ,       
                    sigFunc(2);
                    exit(0);
                }
            }
            if(FD_ISSET(STDIN_FILENO, &rdset)){
                //          ,          ,   3   ,   A1 B
                time_t localtm;
                time(&localtm);//      
                localtm += 8*3600;
                memset(buf, 0, sizeof(buf));//  buf
                int ret = read(STDIN_FILENO, buf, 1024);//    
                if(ret == 0){
                    //              ,      
                    puts("I quite.");
                    break;
                }
                char sstoA1[1024] = {0};//      ,   A1   
                char sstoB[1024] = {0};//      ,   B   
                sprintf(sstoA1, "%ld %d %s", localtm, 3, buf); //          A1
                sprintf(sstoB, "%ld %d %s", localtm, 1, buf); //   1      B
                sndToA1(shmid, semid, p, sstoA1);//   A1
                write(fdWrite, sstoB, sizeof(sstoB));//       B
            }
        }
        close(fdRead);
        close(fdWrite);
        return 1;//        ,  1
    }
    
    int sndToA1(int shmid, int semid, char *p, char *msg){
        //           A1    
        //       ,              ,     
        struct sembuf V;
        V.sem_num = 0;
        V.sem_op = +1;
        V.sem_flg = SEM_UNDO;
        semop(semid, &V, 1);
        /* int shmid = shmget(1000, 4096, IPC_CREAT|0666);//         */
        ERROR_CHECK(shmid, -1, "shmget");
        /* char *p = (char *)shmat(shmid, NULL, 0); */
        memcpy(p, msg, strlen(msg));//         
        return 1;
    }
    
    void closeAll(){
        //               ,       
        write(fdWrite, "0 2 0", 5);//       B
        shmdt(p);
        shmctl(shmid, IPC_RMID, NULL);
        semctl(semid, IPC_RMID, 0);
        close(fdWrite);
        close(fdRead);
        exit(0);
    }
    
    void sigFunc(int signum){
        printf("Bye Bye.
    "); // 2 3 , A1, closeAll sndToA1(shmid, semid, p, "0 2 0");// A1 usleep(500); closeAll(); }
    b.c
    
    //========= B   ===========
    //1.         ,         A  
    //2.   A         
    //3.          ,  A       B1
    //===========================
    
    #include <func.h>
    
    //          ,   B1    
    typedef struct myMsg{
        long mtype;
        char mtext[512];
    }myMsg_t;
    
    int chatB(char *pipe1, char *pipe2);
    int sndToB1(int msqid, char *msg);//  A       B1
    void closeAll();
    void sigFunc(int signum);
    
    //    ,          
    int msqid;
    int fdWrite;
    int fdRead;
    
    int main()
    {
        msqid = msgget(3000, IPC_CREAT|0666);
        ERROR_CHECK(msqid, -1, "B msgget");
    
        //          
        signal(SIGINT, sigFunc);
        signal(SIGQUIT, sigFunc);
    
        int ret = chatB("./1.pipe", "./2.pipe");
        ERROR_CHECK(ret, -1, "run B");
        return 0;
    }
    
    int chatB(char *pipe1, char *pipe2){
        //    2,   2    ,   1   
        fdWrite = open(pipe1, O_WRONLY);
        ERROR_CHECK(fdWrite, -1, "open pipe1");
        fdRead = open(pipe2, O_RDONLY);
        ERROR_CHECK(fdRead, -1, "open pipe2");
        setbuf(stdin, NULL);
        puts("============ B ============");
        char buf[512] = {0};
        fd_set rdset;//    ,    
        while(1){
            //        
            struct timeval timeout;
            timeout.tv_sec = 5;
            timeout.tv_usec = 15000000;
            FD_ZERO(&rdset);//     
            FD_SET(fdRead, &rdset);
            FD_SET(STDIN_FILENO, &rdset);
            int tret = select(fdRead+1,&rdset,NULL,NULL,&timeout);
            if(tret == 0){
                puts("time out!");
            }
    
            //       ,      ,        
            if(FD_ISSET(fdRead, &rdset)){
                //       ,        B1
                memset(buf, 0, sizeof(buf));
                int ret = read(fdRead, buf, 1024);
                if(ret == 0){
                    sigFunc(2);
                    break;
                }
                int type = 0;//         
                sscanf(buf, "%*d %d", &type);//          
    
                //   2   ,      
                // B1      ,        ,     
                if(type == 2){
                    sigFunc(2);
                    exit(0);
                }
    
                //         ,   B1
                int snd_ret = sndToB1(msqid, buf);
                ERROR_CHECK(snd_ret, -1, "B sndToB1");
            }
            if(FD_ISSET(STDIN_FILENO, &rdset)){
                //          ,    ,    A B1
                time_t localtm;
                time(&localtm);//      
                localtm += 8*3600;
                memset(buf, 0, sizeof(buf));
                int ret = read(STDIN_FILENO, buf, 1024);
                if(ret == 0){
                    puts("I quite.");
                    break;
                }
                //             
                char sstoA[1024] = {0};//   A   
                sprintf(sstoA, "%ld %d %s", localtm, 1, buf); 
                write(fdWrite, sstoA, sizeof(sstoA));
    
                char sstoB1[1024] = {0};//   B1      3 
                sprintf(sstoB1, "%ld %d %s", localtm, 3, buf); 
                sndToB1(msqid, sstoB1);
            }
        }
        close(fdRead);
        close(fdWrite);
        return 1;//        ,  1
    }
    
    int sndToB1(int msqid, char *msg){
        //      ,      B1
        myMsg_t msgtoB1;//         
        msgtoB1.mtype = 1;
        memset(msgtoB1.mtext, 0, sizeof(msgtoB1.mtext));
        memcpy(msgtoB1.mtext, msg, strlen(msg));
        msgsnd(msqid, &msgtoB1, strlen(msg), 0);
        return 1;
    }
    
    void closeAll(){
        msgctl(msqid, IPC_RMID, 0);//      
        close(fdWrite);//    
        close(fdRead);
        exit(0);
    }
    
    void sigFunc(int signum){
        printf("Bye Bye.
    "); // , B1, , sndToB1(msqid, "0 2 0");// B1 write(fdWrite, "0 2 0", 5);// A usleep(500);// , B1 // 2 3 , closeAll closeAll(); }
    a 1.
    
    //========== A1 ==========
    //1.          
    //2.  
    
    int display();
    
    #include <func.h>
    
    int main()
    {
        int ret = display();
        ERROR_CHECK(ret, -1, "A1 display");
        return 0;
    }
    
    int display(){
        //1.          
        //       ,      ,      ,     
        //1.1         ,             ,              
        int semid = semget(2000, 1, IPC_CREAT|0666);
        ERROR_CHECK(semid, -1, "A1 semget");
        semctl(semid, 0, SETVAL, 0);//        0
        //     ,      ,       
        struct sembuf P;
        P.sem_num = 0;
        P.sem_op = -1;
        P.sem_flg = SEM_UNDO;
        printf("=========== A1 ===========
    "); while(1){ semop(semid, &P, 1);//P , int shmid = shmget(1000, 4096, IPC_CREAT|0666); ERROR_CHECK(shmid, -1, "A1 shmget"); char *p = (char *)shmat(shmid, NULL, 0);// int type = 0; sscanf(p, "%*d %d", &type);// , switch (type){ case 1: // B printf("<<<<<<<<< receive <<<<<<<<<<
    "); struct tm *ptm = NULL; time_t tmp = 0; char ss[512] = {0}; sscanf(p, "%ld", &tmp);// sscanf(p, "%*d %*d %[^
    ]", ss); ptm = gmtime(&tmp); printf("%4d-%02d-%02d %02d:%02d:%02d
    ", ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); puts(ss); printf("
    "); // memset(p, 0, 4096); break; case 2: printf("Bye Bye.
    "); shmdt(p); shmctl(shmid, IPC_RMID, NULL); exit(0); break; case 3: printf(">>>>>>>>> send >>>>>>>>>>>
    "); struct tm *ptm3 = NULL; time_t tmp3 = 0; char ss3[512] = {0}; sscanf(p, "%ld", &tmp3);// sscanf(p, "%*d %*d %[^
    ]", ss3); ptm3 = gmtime(&tmp3); printf("%4d-%02d-%02d %02d:%02d:%02d
    ", ptm3->tm_year+1900,ptm3->tm_mon+1,ptm3->tm_mday, ptm3->tm_hour, ptm3->tm_min, ptm3->tm_sec); puts(ss3); printf("
    "); // memset(p, 0, 4096); break; default: printf("sonething wrong!
    "); } } }
    b 1.
    
    //========== B1 ===========
    //    B   ,   
    
    #include <func.h>
    
    typedef struct myMsg{
        long mtype;
        char mtext[512];
    }myMsg_t;
    
    int display();
    
    int main()
    {
        int ret = display();
        ERROR_CHECK(ret, -1, "B1 display");
        return 0;
    }
    
    int display(){
        printf("=========== B1 ===========
    "); while(1){ // B int msqid = msgget(3000, IPC_CREAT|0666); ERROR_CHECK(msqid, -1, "B1 msgget"); myMsg_t msgfromB; memset(&msgfromB, 0, sizeof(msgfromB)); msgrcv(msqid, &msgfromB, sizeof(msgfromB.mtext), 1, 0); //1. 2 , int type = 0; sscanf(msgfromB.mtext, "%*d %d", &type);// , , switch (type){ case 1: // B printf("<<<<<<<<< receive <<<<<<<<<<
    "); struct tm *ptm = NULL; time_t tmp = 0; char ss[512] = {0}; sscanf(msgfromB.mtext, "%ld", &tmp);// sscanf(msgfromB.mtext, "%*d %*d %[^
    ]", ss); ptm = gmtime(&tmp); printf("%4d-%02d-%02d %02d:%02d:%02d
    ", ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); puts(ss); printf("
    "); // break; case 2: // printf("Bye Bye.
    "); msgctl(msqid, IPC_RMID, NULL); exit(0); case 3: printf(">>>>>>>>> send >>>>>>>>>>>
    "); struct tm *ptm3 = NULL; time_t tmp3 = 0; char ss3[512] = {0}; sscanf(msgfromB.mtext, "%ld", &tmp3);// sscanf(msgfromB.mtext, "%*d %*d %[^
    ]", ss3); ptm3 = gmtime(&tmp3); printf("%4d-%02d-%02d %02d:%02d:%02d
    ", ptm3->tm_year+1900,ptm3->tm_mon+1,ptm3->tm_mday, ptm3->tm_hour, ptm3->tm_min, ptm3->tm_sec); puts(ss3); printf("
    "); break; default: printf("Something wrong!
    "); } } }
    以下のように実行します

    以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。