实现多个客户端之间的通信(进程之间的通信),服务器作为中转站,并提示哪个客户端上线
运行命令
mkfifo fifo
gcc server.c -o server
gcc client.c -o client
./server fifo
在开三个终端分别输入./client fifo 表示三个客户端
服务器代码
/************************************************************************* > File Name: server.c > Author: yang > Mail:[email protected] > Created Time: 2014年08月23日 星期六 18:59:46 ************************************************************************/ #include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<fcntl.h> typedef struct tag{//储存进程信息 int s_id;//客户端的进程号 int s_fd;//向客户端发送信息的标识符 int s_flag;//标记是否在server的队列里面 }USR,*pUSR; int main(int argc,char *argv[]){ int fd_server; USR ulist[1024]; memset(ulist,0,sizeof(ulist)); int nret; char buf[1024]; fd_server=open(argv[1],O_RDONLY);//之前就建好的管道,负责客户端向server发送 三种信息分别为1)在线 2)客户发送的消息 3)下线 if(fd_server==-1){ perror("error"); exit(1); } fd_set bak_set,ready_set;//bak_set先备份一下 FD_ZERO(&bak_set); FD_SET(fd_server,&bak_set); struct timeval tm;//间隔时间 while(1){ tm.tv_sec=0; tm.tv_usec=1000; ready_set=bak_set; nret=select(fd_server+1,&ready_set,NULL,NULL,&tm);//检测进程中有几个向server发送信息 if(nret==0) continue; if(FD_ISSET(fd_server,&ready_set)){//检测标识符fd_server是否发送信息 memset(buf,0,1024); if(read(fd_server,buf,1024)==0){ continue; } else{ if(strncmp(buf,"on",2)==0){//检测穿来的信息是不是上线信息 int pid; char pipename[32]=""; sscanf(buf+3,"%d",&pid); printf("%d on \n",pid); sprintf(pipename,"%d.fifo",pid); int index; for(index=0;index<1024;index++) if(ulist[index].s_flag==0) break; if(index==1024) printf("full!\n"); else{ ulist[index].s_flag=1; ulist[index].s_id=pid; ulist[index].s_fd=open(pipename,O_WRONLY); } } else if(strncmp(buf,"off",3)==0){//是不是下线信息 int pid; sscanf(buf+3,"%d",&pid); char pipename[32]=""; sprintf(pipename,"%d.fifo",pid); printf("%d off\n",pid); int index; for(index=0;index<1024;index++){ if(ulist[index].s_id==pid){ ulist[index].s_flag=0; ulist[index].s_id=0; close(ulist[index].s_fd); break; } } } else {//其他消息 int index; for(index=0;index<1024;index++){ if(ulist[index].s_flag==1) write(ulist[index].s_fd,buf,strlen(buf)); } } } } } }
客户端代码
/************************************************************************* > File Name: client.c > Author: yang > Mail:[email protected] > Created Time: 2014年08月23日 星期六 19:54:40 ************************************************************************/ #include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<fcntl.h> int main(int argc,char *argv[]){ char pipename[32]=""; int fd_send,fd_recv; sprintf(pipename,"%d.fifo",getpid()); if(-1==mkfifo(pipename,0666)){//根据这个名字建管道 perror("mkfifo"); exit(1); } char msg[1024]=""; sprintf(msg,"on %d\n",getpid()); fd_send=open(argv[1],O_WRONLY); if(fd_send==-1){ perror("open"); exit(1); } write(fd_send,msg,strlen(msg));//发送上线信息 fd_recv=open(pipename,O_RDONLY);//从这个新管道读 if(fd_recv==-1){ perror("open client"); exit(1); } if(fork()==0){//另开辟进程用来读 close(fd_send); while(memset(msg,0,1024),read(fd_recv,msg,1024)>0){ printf("msg>>:"); write(1,msg,strlen(msg)); } close(fd_recv); exit(1); } // close()用来写信息 while(memset(msg,0,1024),fgets(msg,1024,stdin)!=NULL){ write(fd_send,msg,strlen(msg)); } memset(msg,0,1024);//发送下线信息 sprintf(msg,"off %d\n",getpid()); write(fd_send,msg,strlen(msg)); close(fd_send); close(fd_recv); wait(NULL); }