嵌入式——管道实现聊天室(1)

文章目录

  • 一、介绍
    • 1.1 使用的特殊函数
    • 2.1 功能
  • 二、代码
    • 2.1 头文件
    • 2.2 服务器
    • 2.3 客户端
  • 三、演示视频

一、介绍

1.1 使用的特殊函数

1、fork函数:创建父子进程
2、共享内存:实现父子进程之间通讯。
3、mkfifo:创建管道

2.1 功能

聊天室中一人发消息所有人都可以看到。聊天室中可以任意加入或者退出。

二、代码

2.1 头文件

#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];
};

2.2 服务器

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

2.3 客户端

运行可执行文件是要输入两个参数,第二个参数作为私有管道名

#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

你可能感兴趣的:(嵌入式——管道实现聊天室(1))