日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

简洁版即时聊天---I/O多路复用使用

發(fā)布時間:2025/3/15 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简洁版即时聊天---I/O多路复用使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、基于select接口+有名管道的I/O 多路復用

???????1、注意提示點:

???????????????????????????? 1、基于客戶端以及服務器兩端的使用

???????????????????????????? 2 、對于有名管道,須注意有名管道的鏈接順序,否則,可能發(fā)生死鎖,或鏈接不成功。

???????????????????????????? 3、學會select接口的使用。

??????? 2、select函數(shù)的數(shù)據(jù)結(jié)構(gòu)

#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)); //若果沒有接到結(jié)束符,就以為一直要輸入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; }


二、融入共享內(nèi)存和信號鎖的 I/O多路復用的簡潔版即時聊天


1、需求陳述: ???????AB 兩個進程通過管道通信, 像以前的互相聊天一樣, 然后 A 進程每次接收到的數(shù)據(jù)通過 A1 進程顯
示( 一個新進程, 用于顯示A 接收到的信息) , A A1 間的數(shù)據(jù)傳遞采用共享內(nèi)存, 對應的有一個 B1
進程, 用于顯示B 進程接收到的信息。 針對 AB 進程, 退出時采用 ctrl+c 退出, 當收到對應信號后,
自身進程能夠通過信號處理函數(shù)進行資源清理, 清理后exit 退出進程。 ( A1B1, 手動關(guān)閉即可) 。 界
面圖如下。
?????

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;//退出處理函數(shù) 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;}//信號量設置初始化和共享內(nèi)存初始化//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;}//共享內(nèi)存//int shmid;shmid=shmget(10003,500,IPC_CREAT|0600);if(-1==shmid){perror("shmid");return -1;}//共享內(nèi)存結(jié)構(gòu)體//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)); //若果沒有接到結(jié)束符,就以為一直要輸入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; //控制打印次數(shù)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 main() {//連接共享內(nèi)存和信號量int sem;sem=semget(12356,1,IPC_CREAT|0600);int ret;int shmid;shmid=shmget(10003,500,IPC_CREAT|0600);shminf *pshow;pshow=(shminf *)shmat(shmid,NULL,0);while(1){if(2==pshow->flag){printf("Girl:%s",pshow->buf);pshow->flag=0;}if(1==pshow->flag){printf("Boy:%s",pshow->buf);pshow->flag=0;}if(3==pshow->flag){pshow->flag=0;printf("byebye!\n");kill(getpid(),SIGINT);// break;}}return 0; }

女孩聊天主程序:#include"func.h"//部分全局變量 int sem,shmid,fdr,fdw; shminf *p;//退出處理函數(shù) 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;}//信號量設置初始化和共享內(nèi)存初始化//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;}//共享內(nèi)存// int shmid;shmid=shmget(1000,500,IPC_CREAT|0600);if(-1==shmid){perror("shmid");return -1;}// shminf *p; //共享內(nèi)存結(jié)構(gòu)體//首先將flag置為0,表示初始時buff里面沒消息p=(shminf *)shmat(shmid,NULL,0);if(p==(shminf *)-1){perror("shmat");return -1;}//將標志數(shù)組全置為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; //控制打印次數(shù)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; }


女孩顯示窗口:#include"func.h"int main() {//連接共享內(nèi)存和信號量int sem;sem=semget(12345,1,IPC_CREAT|0600);int ret;int shmid;shmid=shmget(1000,500,IPC_CREAT|0600);shminf *pshow;pshow=(shminf *)shmat(shmid,NULL,0);while(1){if(1==pshow->flag){printf("Girl:%s",pshow->buf);pshow->flag=0;}if(2==pshow->flag){printf("Boy:%s",pshow->buf);pshow->flag=0;}if(3==pshow->flag){printf("byebye!");pshow->flag=0;kill(getpid(),SIGINT);}}return 0; }


三、大文件內(nèi)存映射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; }

總結(jié)

以上是生活随笔為你收集整理的简洁版即时聊天---I/O多路复用使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。