简洁版即时聊天---I/O多路复用使用
生活随笔
收集整理的這篇文章主要介紹了
简洁版即时聊天---I/O多路复用使用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、基于select接口+有名管道的I/O 多路復用
???????1、注意提示點:
???????????????????????????? 1、基于客戶端以及服務器兩端的使用
???????????????????????????? 2 、對于有名管道,須注意有名管道的鏈接順序,否則,可能發生死鎖,或鏈接不成功。
???????????????????????????? 3、學會select接口的使用。
??????? 2、select函數的數據結構
#include <sys/time.h>#include <sys/types.h>#include <unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);void FD_CLR(int fd, fd_set *set);int FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set); struct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */};3、客戶端以及服務端源代碼頭文件: #include <string.h> #include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h>客戶端: #include"func.h"int main(int argc,char *argv[]) {if(3!=argc){printf("error argcs!\n");return -1;}int fdr,fdw;fdr=open(argv[1],O_RDONLY); //打開管道一的讀端if(-1==fdr){perror("open1");return -1;}fdw=open(argv[2],O_WRONLY); //打開管道二的寫端if(-1==fdw){perror("open2");return -1;}printf("Now I can receive:fdr=%d,fdw=%d\n",fdr,fdw);int ret; char buff[35];struct timeval t;t.tv_sec=3;t.tv_usec=0;fd_set fd_rd; //只用檢測讀即可while(1){FD_ZERO(&fd_rd);FD_SET(fdr,&fd_rd);FD_SET(0,&fd_rd);ret=select(fdr+1,&fd_rd,NULL,NULL,&t);if(FD_ISSET(fdr,&fd_rd)){memset(buff,0,sizeof(buff));ret=read(fdr,buff,sizeof(buff));if(ret>0){printf("TWO:");puts(buff);}else{printf("byebye!\n");break;}}if(FD_ISSET(0,&fd_rd)){memset(buff,0,sizeof(buff));//puts("請輸入:");ret=read(0,buff,sizeof(buff));if(ret>0){write(fdw,buff,strlen(buff)-1);}else{printf("byebyei\n");break;}}}return 0; }服務端:#include"func.h"int main(int argc,char *argv[]) {if(3!=argc){printf("error argcs!\n");return -1;}int fdr,fdw;fdw=open(argv[1],O_WRONLY); //打開管道一的寫端if(-1==fdw){perror("open1");return -1;}fdr=open(argv[2],O_RDONLY); //打開管道二的讀端if(-1==fdr){perror("open2");return -1;}printf("fdw=%d,fdr=%d\n",fdw,fdr);char buff[30]={0};fd_set fd_rd;int ret;struct timeval t;t.tv_usec=0;while(1){ FD_ZERO(&fd_rd);FD_SET(0,&fd_rd);FD_SET(fdr,&fd_rd);t.tv_sec=30;ret=select(fdr+1,&fd_rd,NULL,NULL,&t);if(ret>0){if(FD_ISSET(0,&fd_rd)){memset(buff,0,sizeof(buff));//puts("請輸入:");ret=read(0,buff,sizeof(buff)); //若果沒有接到結束符,就以為一直要輸入if(ret>0){write(fdw,buff,strlen(buff)-1);}else{printf("byebye!\n");break;}}if(FD_ISSET(fdr,&fd_rd)){memset(buff,0,sizeof(buff));ret=read(fdr,buff,sizeof(buff));if(ret>0){printf("ONE:");puts(buff);}}}else{printf("no fd read!\n");break;}}return 0; }
二、融入共享內存和信號鎖的 I/O多路復用的簡潔版即時聊天
1、需求陳述: ???????A,B 兩個進程通過管道通信, 像以前的互相聊天一樣, 然后 A 進程每次接收到的數據通過 A1 進程顯
示( 一個新進程, 用于顯示A 接收到的信息) , A 和 A1 間的數據傳遞采用共享內存, 對應的有一個 B1
進程, 用于顯示B 進程接收到的信息。 針對 A,B 進程, 退出時采用 ctrl+c 退出, 當收到對應信號后,
自身進程能夠通過信號處理函數進行資源清理, 清理后exit 退出進程。 ( A1,B1, 手動關閉即可) 。 界
面圖如下。?????
2、源代碼
頭文件:#include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h> #include<sys/ipc.h> #include<sys/shm.h> #include<sys/sem.h> #include<string.h> #include<signal.h> #include<stdlib.h>typedef struct Shminfo{short flag;char buf[50]; }shminf;
男孩聊天主程序:#include"func.h"//部分定義全局變量 int sem,shmid,fdr,fdw; shminf *p;//退出處理函數 void sighandle(int signum) {//printf("I am in out!\n");p->flag=3;sleep(1);semctl(sem,IPC_RMID,0);shmdt(p);int handret;handret=shmctl(shmid,IPC_RMID,0);//close(fdr);//close(fdw);kill(getpid(),SIGINT);close(fdr);close(fdw);exit(0); }int main(int argc,char *argv[]) {signal(SIGINT,sighandle);if(3!=argc){printf("error argcs!\n");return -1;}//信號量設置初始化和共享內存初始化//int sem;sem=semget(12356,1,IPC_CREAT|0600);if(-1==sem){perror("semget");return -1;}int ret;ret=semctl(sem,0,SETVAL,1);if(-1==ret){perror("semctl");return -1;}//共享內存//int shmid;shmid=shmget(10003,500,IPC_CREAT|0600);if(-1==shmid){perror("shmid");return -1;}//共享內存結構體//shminf *p;p=(shminf *)shmat(shmid,NULL,0);if(p==(shminf *)-1){perror("shmat");return -1;}p->flag=0;memset(p->buf,0,sizeof(p->buf));//初始化P 和 V 的初值struct sembuf sopp,sopv;memset(&sopp,0,sizeof(sopp));memset(&sopv,0,sizeof(sopv));sopp.sem_num=0;sopp.sem_op=-1;sopp.sem_flg=SEM_UNDO;sopv.sem_num=0;sopv.sem_op=1;sopv.sem_flg=SEM_UNDO;//管道的連接//int fdr,fdw;fdw=open(argv[1],O_WRONLY); //打開管道一的寫端if(-1==fdw){perror("open1");return -1;}fdr=open(argv[2],O_RDONLY); //打開管道二的讀端if(-1==fdr){perror("open2");return -1;}printf("fdw=%d,fdr=%d\n",fdw,fdr);char buff[30]={0};fd_set fd_rd;//int ret;//struct timeval t;//t.tv_usec=0;while(1){ FD_ZERO(&fd_rd);FD_SET(0,&fd_rd);FD_SET(fdr,&fd_rd);//t.tv_sec=30;ret=select(fdr+1,&fd_rd,NULL,NULL,NULL);//if(ret>0)//{if(FD_ISSET(0,&fd_rd)){memset(buff,0,sizeof(buff));//puts("請輸入:");ret=read(0,buff,sizeof(buff)); //若果沒有接到結束符,就以為一直要輸入if(ret>0){memset(p->buf,0,sizeof(p->buf));semop(sem,&sopp,1);strcpy(p->buf,buff);p->flag=1;semop(sem,&sopv,1);write(fdw,buff,strlen(buff));}//else{//p->flag=3;//sleep(1);// kill(getpid(),SIGINT);// signal(SIGQUIT,sighandle);//printf("byebye!\n");//break;// signal(SIGINT,sighandle);//}}if(FD_ISSET(fdr,&fd_rd)){memset(buff,0,sizeof(buff));ret=read(fdr,buff,sizeof(buff));if(ret>0){memset(p->buf,0,sizeof(p->buf));semop(sem,&sopp,1);strcpy(p->buf,buff);p->flag=2; //控制打印次數semop(sem,&sopv,1);//測試語句兩行//printf("Girl:");//puts(buff);}else{p->flag=3;sleep(1);semctl(sem,IPC_RMID,0);shmdt(p);int handret;handret=shmctl(shmid,IPC_RMID,0);kill(getpid(),SIGINT);close(fdr);close(fdw);exit(0);//signal(SIGQUIT,sighandle);//printf("byebye!\n");//break;}}//signal(SIGQUIT,sighandle);/*}else{printf("no fd read!\n");break;}*/}return 0; }
女孩聊天主程序:#include"func.h"//部分全局變量 int sem,shmid,fdr,fdw; shminf *p;//退出處理函數 void sighandle(int signum) {//printf("I am in out!\n");p->flag=3;sleep(1);semctl(sem,IPC_RMID,0);shmdt(p);int handret;handret=shmctl(shmid,IPC_RMID,0);kill(getpid(),SIGINT);close(fdr);close(fdw);exit(0); } int main(int argc,char *argv[]) {signal(SIGINT,sighandle);if(3!=argc){printf("error argcs!\n");return -1;}//信號量設置初始化和共享內存初始化//int sem;sem=semget(12345,1,IPC_CREAT|0600);if(-1==sem){perror("semget");return -1;}int ret;//初始化鎖的值ret=semctl(sem,0,SETVAL,1); if(-1==ret){perror("semctl");return -1;}//共享內存// int shmid;shmid=shmget(1000,500,IPC_CREAT|0600);if(-1==shmid){perror("shmid");return -1;}// shminf *p; //共享內存結構體//首先將flag置為0,表示初始時buff里面沒消息p=(shminf *)shmat(shmid,NULL,0);if(p==(shminf *)-1){perror("shmat");return -1;}//將標志數組全置為0p->flag=0;memset(p->buf,0,sizeof(p->buf));//初始化P 和 V 的初值struct sembuf sopp,sopv;memset(&sopp,0,sizeof(sopp));memset(&sopv,0,sizeof(sopv));sopp.sem_num=0;sopp.sem_op=-1;sopp.sem_flg=SEM_UNDO;sopv.sem_num=0;sopv.sem_op=1;sopv.sem_flg=SEM_UNDO;//管道的連接//int fdr,fdw;fdr=open(argv[1],O_RDONLY); //打開管道一的讀端if(-1==fdr){perror("open1");return -1;}fdw=open(argv[2],O_WRONLY); //打開管道二的寫端if(-1==fdw){perror("open2");return -1;}printf("Now I can receive:fdr=%d,fdw=%d\n",fdr,fdw);char buff[35];//struct timeval t;//t.tv_sec=3;//t.tv_usec=0;fd_set fd_rd; //只用檢測讀即可while(1){FD_ZERO(&fd_rd);FD_SET(fdr,&fd_rd);FD_SET(0,&fd_rd);ret=select(fdr+1,&fd_rd,NULL,NULL,NULL);if(FD_ISSET(fdr,&fd_rd)){memset(buff,0,sizeof(buff));ret=read(fdr,buff,sizeof(buff));if(ret>0){memset(p->buf,0,sizeof(p->buf));semop(sem,&sopp,1);strcpy(p->buf,buff);p->flag=2; //控制打印次數semop(sem,&sopv,1);//測試語句兩行//printf("Boy:");//puts(buff);}else{//printf("byebye!\n");p->flag=3;sleep(1);semctl(sem,IPC_RMID,0);shmdt(p);int handret;handret=shmctl(shmid,IPC_RMID,0);kill(getpid(),SIGINT);close(fdr);close(fdw);//signal(SIGQUIT,sighandle);//break;}}if(FD_ISSET(0,&fd_rd)){memset(buff,0,sizeof(buff));//puts("請輸入:");ret=read(0,buff,sizeof(buff));if(ret>0){memset(p->buf,0,sizeof(p->buf));semop(sem,&sopp,1);strcpy(p->buf,buff);p->flag=1;semop(sem,&sopv,1);write(fdw,buff,strlen(buff));}else{//printf("byebyei\n");p->flag=3;sleep(1);kill(getpid(),SIGINT);//signal(SIGQUIT,sighandle);//break;}//else //signal(SIGINT,sighandle);}}return 0; }
三、大文件內存映射mmap實例
源代碼如下:#include <sys/mman.h> #include <sys/types.h> //頭文件 #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include<stdio.h> #include<string.h>int main(int argc,char *argv[]) {if(3!=argc){printf("error argcs!\n");return -1;}int fd1,fd2;struct stat fd;fd1=open(argv[1],O_RDWR);fd2=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);char *p,*p1;int ret;fstat(fd1,&fd);truncate(argv[2],fd.st_size); //必須先有空間之后才能進行操作。//ret=fd.st_size; // printf("ret=%d\n",ret);//char buff[fd.st_size+1];p=(char *)mmap(NULL,fd.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd1,0);p1=(char *)mmap(NULL,fd.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd2,0);memcpy(p1,p,fd.st_size); //memcpy - copy memory areamunmap(p,fd.st_size);munmap(p1,fd.st_size);close(fd1);close(fd2);return 0; }
總結
以上是生活随笔為你收集整理的简洁版即时聊天---I/O多路复用使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 乾坤大挪移,巧迁数据到proxmox平台
- 下一篇: MapServer WinForm开发成