Linux 管道通信 客户端与服务器通信

实现多个客户端之间的通信(进程之间的通信),服务器作为中转站,并提示哪个客户端上线

运行命令

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);
}





你可能感兴趣的:(Linux 管道通信 客户端与服务器通信)