一、介绍
在我以前发的聊天室的基础上增加私聊功能。
想要对某个用户私聊需要,私聊用户名+@+内容
二、代码
2.1 头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <signal.h>
#include<unistd.h>
#include<sys/stat.h>
#include <fcntl.h>
#include<linux/stat.h>
#include<sys/types.h>
#include<string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#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 ts1=':';char ts2='@';
char buf1[SIZE],buf2[SIZE],buf_name[SIZE],bufj1[SIZE],bufj2[SIZE];
char buf_data[SIZE][SIZE];
struct shareMemory{
int num;
char bufs[SIZE];
char buf_pri_name[100][100];
};
2.2 服务器
#include"CharRoom3.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"CharRoom3.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){
sprintf(buf2,"%s@",buf_name);
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){
if(strstr(buf1,"@")!=NULL){
if(strstr(buf1,buf2)!=NULL){
for(int i=0;i<strlen(buf1);i++){
if(buf1[i]!=ts1)
bufj1[i]=buf1[i];
else break;
}
for(int i=0;i<strlen(buf1);i++){
if(buf1[i]!=ts2)
continue;
else {
for(int j=i+1;j<strlen(buf1);j++)
bufj2[j-i-1]=buf1[j];
break;
}
}
sprintf(buf1,"%s private chat you:%s",bufj1,bufj2);
printf("%s\n",buf1);}
}
else
printf("%s\n",buf1);}}
}}
}
三、演示视频
链接:https://pan.baidu.com/s/15pZ3TPlj1ioBKYuYfcTmdA
提取码:o29f