1、fork函数:创建父子进程
2、共享内存:实现父子进程之间通讯。
3、mkfifo:创建管道
聊天室中一人发消息所有人都可以看到。聊天室中可以任意加入或者退出。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pubpipe "public"
#define SIZE 1024
#define KEY 99
int w_num;
int *shm=NULL;
int shmid;
int run=1;
int fd,fd1;
pid_t pid,pid2;
char buf1[SIZE],buf2[SIZE],buf_name[SIZE];
char buf_data[SIZE][SIZE];
struct shareMemory{
int num;
char bufs[SIZE];
char buf_pri_name[100][100];
};
#include"CharRoom2.h"
void main()
{
struct shareMemory *shared;
if((shmid=shmget(KEY,SIZE,0666|IPC_CREAT))==-1){
perror("Fail to shmget");
exit(EXIT_SUCCESS);}
//创建公用管道
if((mkfifo(pubpipe,0777)<0)&&(errno!=EEXIST)){
printf("cannot create fifo...\n");exit(1);}
//共享内存,初始化
shm = shmat(shmid,0,0);
shared = (struct shareMemory *)shm;
if(shared->num!=0)
shared->num=0;
pid=fork();
if(pid>0){
shm = shmat(shmid,0,0); //设置共享内存
shared = (struct shareMemory *)shm;
while(1){
shared->num=shared->num;
if((fd=open(pubpipe,O_RDONLY))==-1){
printf(" open pubpipe error\n");exit(1);}
if(read(fd,buf1,SIZE)<0){
printf("read error!\n");exit(1);}
if(strncmp(buf1,"pipename",8)==0){
memcpy(shared->buf_pri_name[shared->num],buf1+8,20);
printf("new pipe name:%s\n",shared->buf_pri_name[shared->num]);
shared->num+=1;printf("当前在线人数:%d\n",shared->num);
memset(buf1, 0, sizeof(buf1));continue;}
strcpy(shared->bufs,buf1);}
if(shmdt(shm)==-1) //把共享内存从当前进程分离
{
perror("Fail to shmdt");
exit(1);
}
}
else{
shm = shmat(shmid,0,0); //设置共享内存
shared = (struct shareMemory *)shm;
while(1){
if(strncmp(buf2,shared->bufs,strlen(shared->bufs))!=0){
for(int ns=0;ns<shared->num;ns++){
if((fd1=open(shared->buf_pri_name[ns],O_WRONLY))==-1){
printf("删除第%d个管道\n",ns);
printf("%s pipe delete!\n",shared->buf_pri_name[ns]);
for(int k=ns;k<shared->num;k++)
strcpy(shared->buf_pri_name[k],shared->buf_pri_name[k+1]);
shared->num-=1;printf("当前在线人数:%d\n",shared->num);continue;}
if(write(fd1,shared->bufs,SIZE)<0){
printf("write error!\n");exit(1);}
}
strcpy(buf2,shared->bufs);
}
}
if(shmdt(shm)==-1) //把共享内存从当前进程分离
{
perror("Fail to shmdt");
exit(1);
}
}
}
运行可执行文件是要输入两个参数,第二个参数作为私有管道名
#include"CharRoom2.h"
void main(int argc,char* argv[])
{
//判断参数个数
if(argc!=2){
printf("parameter error!\n");exit(1);}
// 创建私有管道,如果有则直接使用
if((mkfifo(argv[1],0777)<0)&&(errno!=EEXIST))
{
printf("cannot create %s fifo error!\n",argv[1]);
exit(1);
}
//发送私有管道名给服务器
sprintf(buf1,"pipename%s",argv[1]);
if((fd=open(pubpipe,O_WRONLY))==-1){
printf(" open pubpipe error\n");exit(1);}
if(write(fd,buf1,SIZE)<0){
printf("write error!\n");exit(1);}
close(fd);
//注册
printf("请输入你的昵称:");scanf("%s",buf_name);
printf("%d\n",getpid());
system("date +%m-%d-%I:%M");
printf("欢迎%s进入聊天室\n",buf_name);
//父子进程实现通讯
pid=fork();
if(pid>0){while(1){
if((fd=open(pubpipe,O_WRONLY))==-1){
printf(" open pubpipe error\n");exit(1);}
scanf("%s",buf1);
sprintf(buf2,"%s说:",buf_name);
strcat(buf2,buf1);
if(write(fd,buf2,SIZE)<0)
{ printf("write error!\n");exit(1);}
if(strcmp(buf1,"quit")==0){
unlink(argv[1]); exit(1);}
}}
else{while(1){
memset(buf1, 0, sizeof(buf1));
if((fd1=open(argv[1],O_RDWR))==-1){
printf(" open pripipe error\n");exit(1);}
if(read(fd1,buf1,SIZE)<0){
printf("write error!\n");exit(1);}
if(strlen(buf1)!=0){
if(strncmp(buf1,buf_name,strlen(buf_name))!=0)
printf("%s\n",buf1);}
}}
}
链接:https://pan.baidu.com/s/1SODqlYQzCTid78MDgWqVpw
提取码:fnme