Linux下利用命名管道实现简单的聊天室

1、服务器端

①先建立一个Sever_FIFO文件 用于接收来自不同客户端的数据,所有客户端的数据都会发送至这个文件,经过处理后再转存到别的文件之后才会发送到另一个客户端上。
②利用结构体传输过来客户端的pid,并将pid存在pid【】数组中,pid的值是用来区分将信息回传的依据。
③通过简单的pid区分传来的结构体中的数据应该回传的文件,并将数据写入该文件。不停的重复此步骤。

2、客户端
①根据自己的pid创建fifo文件。
②用fork创建进程,父进程用于输入聊天的内容,子进程用于接收根据自己pid创建的fifo中的数据,一旦数据有改变,立即输出到屏幕上。



以下是服务器端的代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#define Server_FIFO_Name "serv_fifo"
#define Client_FIFO_Name "client_fifo_%d"
                                                                                    //----------------------
#define BufSize 200


struct data_to_pass{
pid_t client_pid;
char str[BufSize];
};








int main(){
int server_fifo_fd,client_fifo_fd,pid[2]={0,0};
struct data_to_pass my_data;
int read_res;
char client_fifo[256];
char *char_ptr;




mkfifo(Server_FIFO_Name,0777);
/
server_fifo_fd = open(Server_FIFO_Name , O_RDONLY);
if( -1 == server_fifo_fd ){
fprintf( stderr , "Server fifo failure\n" );
exit(EXIT_FAILURE);
}
//从管道中读取数据。
read_res = read ( server_fifo_fd , &my_data , sizeof(my_data));
printf("%d\n",my_data.client_pid);
pid[0]=my_data.client_pid;


while(pid[1]==0)
{
server_fifo_fd = open(Server_FIFO_Name , O_RDONLY);
if( -1 == server_fifo_fd ){
fprintf( stderr , "Server fifo failure\n" );
exit(EXIT_FAILURE);
}
//从管道中读取数据。
read_res = read ( server_fifo_fd , &my_data , sizeof(my_data));
printf("%d\n",my_data.client_pid);
if(pid[0]!=my_data.client_pid)
pid[1]=my_data.client_pid;
}
//
Again: //用goto去实现循环监听请求.
//打开服务器端口,等待读取。此时如果客户端还未写入数据服务器端会被阻塞。
server_fifo_fd = open(Server_FIFO_Name , O_RDONLY);
if( -1 == server_fifo_fd ){
fprintf( stderr , "Server fifo failure\n" );
exit(EXIT_FAILURE);
}
//从管道中读取数据。
read_res = read ( server_fifo_fd , &my_data , sizeof(my_data));
printf("%d\n",my_data.client_pid);
if(pid[0]==my_data.client_pid) my_data.client_pid=pid[1];
else if(pid[1]==my_data.client_pid) my_data.client_pid=pid[0];
if(read_res > 0)
{
//将客户端的pid号加入回送管道文件名中.
sprintf ( client_fifo, Client_FIFO_Name , my_data.client_pid);
//打开回送管道。
//printf(client_fifo);


client_fifo_fd = open ( client_fifo , O_WRONLY );
if( -1 != client_fifo_fd )
{
//向管道中写入返回的数据.
write ( client_fifo_fd , &my_data, sizeof(my_data));
close ( client_fifo_fd );
}
}
close(server_fifo_fd);


goto Again;
unlink(Server_FIFO_Name);


exit(EXIT_SUCCESS);
}



以下是客户端的代码:

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#define Server_FIFO_Name "serv_fifo"
#define Client_FIFO_Name "client_fifo_%d"


#define BufSize 200


struct data_to_pass{
pid_t client_pid;
char str[BufSize];
};


int main(){
int server_fifo_fd,client_fifo_fd;
struct data_to_pass mydata;
int times_to_send;
char client_fifo[256],s[256];
int rst,pid;


//打开服务器管道,开始写入. 采用NON_BLOCK方式,所以需要服务器先打开。
server_fifo_fd = open(Server_FIFO_Name,O_WRONLY | O_NONBLOCK);
if(server_fifo_fd == -1)
{
fprintf(stderr , "Sorry ,No Server\n");
exit(EXIT_FAILURE);
}
//获得当前进程PID存入结构中。
mydata.client_pid = getpid();
sprintf ( client_fifo,Client_FIFO_Name,mydata.client_pid);
mkfifo(client_fifo,0777);


write(server_fifo_fd , &mydata , sizeof(mydata));


pid=fork();
   if(pid<0)
   {
printf("fork error!\n");
exit(1);
   }


Again:
   if(pid>0)//父进程
   {
gets(s);
//填写发送的数据包.
sprintf(mydata.str,s);
//向管道中写入数据:发送.
write(server_fifo_fd , &mydata , sizeof(mydata));


   }
   else if(pid==0)//子进程
   {


//打开回送管道,等待接受从服务器返回的数据。
client_fifo_fd = open(client_fifo,O_RDONLY);
if(client_fifo_fd != -1)
{
   rst = read( client_fifo_fd , &mydata , sizeof(mydata));
   if( rst > 0)
   {
       printf("received : %s\n",mydata.str);
   }
   close(client_fifo_fd);
}
}
goto Again;
close(server_fifo_fd);
unlink(client_fifo);
exit(EXIT_SUCCESS);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值