1. 程式人生 > >擼程式碼--類QQ聊天實現(基於linux 管道 訊號 共享記憶體)

擼程式碼--類QQ聊天實現(基於linux 管道 訊號 共享記憶體)

一:任務描述

             AB兩個程序通過管道通訊,像以前的互相聊天一樣,然後A程序每次接收到的資料通過A1程序顯示(一個新程序,用於顯示A接收到的資訊),AA1間的資料傳遞採用共享記憶體,對應的有一個B1程序,用於顯示B程序接收到的資訊。針對AB程序,退出時採用ctrl+c退出,當收到對應訊號後,自身程序能夠通過訊號處理函式進行資源清理,清理後exit退出程序。(A1B1,手動關閉即可)。介面圖如下。

:程式碼展示

A程序

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>

int shm_id;

struct t
{
        char buf[128];
};

struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//刪除共享記憶體
        printf("delete OK........\n");
        exit(0);

}

int main()
{//A程序

        signal(SIGINT,hanle);//捕捉 ctrl+c訊號

        shm_id=shmget((key_t)1234,4096,0600|IPC_CREAT);
//建立了一個共享記憶體

//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);//拿到記憶體的指標結構體

        int f1;
        f1=open("1.fifo",O_WRONLY);//對1 開啟寫端

        int f2;
        f2=open("2.fifo",O_RDONLY);//對2 開啟讀端

        fd_set readset;
        //定義了可讀集合
        int maxfd;
        maxfd=STDIN_FILENO > f2 ? STDIN_FILENO+1:f2+1;

        struct timeval check;
        check.tv_sec=1;//設定檢視時間是一秒
        char buf[128];
        while(1)
        {
         FD_ZERO(&readset);//初始化
         FD_SET(STDIN_FILENO,&readset);//新增監控物件
         FD_SET(f2,&readset);
         select(maxfd,&readset,NULL,NULL,&check);//返回可讀的監控物件

         if(FD_ISSET(STDIN_FILENO,&readset))
          {//如果監控到了1管道中有標準輸入 那麼獲取到資料 寫到管道中
           memset(buf,0,sizeof(buf));
           fgets(buf,sizeof(buf),stdin);
           buf[strlen(buf)-1]='\0';
           write(f1,buf,sizeof(buf));//寫到管道1中
           
          }
         if(FD_ISSET(f2,&readset))
          {//監控到了管道2中可以讀
           memset(buf,0,sizeof(buf));
           read(f2,buf,sizeof(buf));//從管道2中讀到buf了
           strcpy(p->buf,buf);//將管道2中讀到的buf 弄到共享記憶體
           printf("from 2:  %s\n",buf);
          }
         if(strcmp(buf,"bye")==0)
          {
           break;
          }

        }
        exit(0);
}

B程序
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int shm_id;
struct t
{
        char buf[128];
};
struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//刪除共享記憶體
        printf("delete OK........\n");
        exit(0);

}
int main()
{//B程序

        signal(SIGINT,hanle);
         shm_id=shmget((key_t)1235,4096,0600|IPC_CREAT);

//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);

        int f1;
        f1=open("1.fifo",O_RDONLY);//對1 開啟讀端

        int f2;
     f2=open("2.fifo",O_WRONLY);//對2 開啟寫端

        fd_set readset;
        //定義了可讀集合
        int maxfd;
        maxfd=STDIN_FILENO > f1 ? STDIN_FILENO+1:f1+1;

        struct timeval check;
        check.tv_sec=1;//設定檢視時間是一秒
        char buf[128];
        while(1)
        {
         FD_ZERO(&readset);//初始化
         FD_SET(STDIN_FILENO,&readset);//新增監控物件
         FD_SET(f1,&readset);
         select(maxfd,&readset,NULL,NULL,&check);//返回可讀的監控物件

         if(FD_ISSET(STDIN_FILENO,&readset))
          {//如果監控到了1管道中有標準輸入 那麼獲取到資料 寫到管道中
           memset(buf,0,sizeof(buf));
           fgets(buf,sizeof(buf),stdin);
           buf[strlen(buf)-1]='\0';
           write(f2,buf,sizeof(buf));//寫到管道2中
          }
         if(FD_ISSET(f1,&readset))
          {//監控到了管道2中可以讀
           memset(buf,0,sizeof(buf));
           read(f1,buf,sizeof(buf));//從管道1中讀
           strcpy(p->buf,buf);//將讀出的字元 放到共享記憶體中
           printf("from 1:  %s\n",buf);
          }
         if(strcmp(buf,"bye")==0)
          {
           break;
          }

        }
        exit(0);
}

A1程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>

int shm_id;
struct t
{
        char buf[128];
};
struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//刪除共享記憶體
        printf("delete OK........\n");
        exit(0);
}

int main()
{
         shm_id=shmget((key_t)1234,4096,0600|IPC_CREAT);
        //獲得了共享記憶體
//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);//這個也拿到了
        char s[128]={0};
        while(1)
        {
        if(strcmp(s,p->buf)!=0)
        {//字串不相同  那麼就打印出來
        strcpy(s,p->buf);
        printf("from B   :%s\n",p->buf);
        }
        }

        exit(0);
}



B1程序

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>

int shm_id;
struct t
{
        char buf[128];
};
struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//刪除共享記憶體
        printf("delete OK........\n");
        exit(0);

}
int main()
{
         shm_id=shmget((key_t)1235,4096,0600|IPC_CREAT);
        //獲得了共享記憶體
//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);//這個也拿到了
        char s[128]={0};
        while(1)
        {
        if(strcmp(s,p->buf)!=0)
        {//字串不相同  那麼就打印出來
        strcpy(s,p->buf);
        printf("from A   :%s\n",p->buf);
        }
        }
        exit(0);
}</span><span style="font-size:18px;">
</span>


三:結果顯示