思路:
运用共享内存来存储当前聊天的人数,消息队列来存储消息,线程来实现读取。
先通过create.c来创建共享内存,并初始化
在chat.c中实现信息的读取,在主函数中将消息写进消息队列中,创建线程来实现消息的读取。
每运行一次chatc.c文件,共享内存存储数加1,实现人数的相加,并用for语句将语句写入消息队列中(有多少个人就写多少条)
在线程 void *read2(void *arg) 函数中从消息队列中读取信息并打印,并用全局变量temp记录消息类型,当检测到发送方为自身时跳过这次循环,不予打印。
signal(SIGINT,func); 发送信号 ,当按下Ctrl +C 时,将共享内存中存储的人数减一并退出程序。
create.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
//1.获取key
key_t key = ftok(".",'c');
if(key==-1){
perror("ftok");
exit(-1);
}
//2.通过key创建ID
int shmid = shmget(key,4,IPC_CREAT|0666); //4是字节大小
if(shmid==-1){
perror("shmget");
exit(-2);
}
//3.映射共享内存
void *p = shmat(shmid,0,0);
if(p==(void *)-1){
perror("shmat");
exit(-3);
}
//4.使用共享内存
*((int *)p) = 0;
//5.解除映射
shmdt(p);
return 0;
}
chat.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <signal.h>
struct MSG{
long mtype;//消息类型
char buf[100];//消息数据
};
int temp;
int msqid;
void func(int sig) //按CTRL +c 退出并进行人数的减1
{
key_t key = ftok(".",'c');
if(key==-1)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid==-1){
perror("shmget");
exit(-2);
}
//3.映射共享内存
void *p = shmat(shmid,0,0);
if(p==(void *)-1){
perror("shmat");
exit(-3);
}
(*((int *)p))--;
exit(1);
}
void *read2(void *arg) //从消息队列中获取信息
{
struct MSG msg1;
while(1)
{
int res = msgrcv(msqid,&msg1,sizeof(msg1.buf),0,0);
if(res==-1)
{
perror("msgrcv");
exit(-3);
}
if(msg1.mtype==temp)
continue;
printf("收到:%s",msg1.buf);
}
}
int main()
{
signal(SIGINT,func);
pthread_t id1;
key_t key = ftok(".",'c');
if(key==-1)
{
perror("ftok");
exit(-1);
}
int msqid = msgget(key,IPC_CREAT|0666);
if(msqid==-1){
perror("msgget");
exit(-2);
}
//--------------------线程
int res = pthread_create(&id1,0,read2,0);
if(res)
{
printf("%s\n",strerror(res));
//exit(-1);
}
//-------------------------获取共享内存
int shmid = shmget(key,0,0);
if(shmid==-1){
perror("shmget");
exit(-2);
}
//3.映射共享内存
void *p = shmat(shmid,0,0);
if(p==(void *)-1){
perror("shmat");
exit(-3);
}
temp=++(*((int *)p)); //人数加1
//--------------------------消息队列
//3.发送消息
struct MSG msg1;
msg1.mtype = (*((int *)p));
int i;
while(1)
{
fgets(msg1.buf,100,stdin);
for(i=0;i<*((int *)p);i++)
{
msgsnd(msqid,&msg1,sizeof(msg1.buf),0);
}
}
pthread_join(id1,0); //等待线程结束
shmdt(p);
return 0;
}

运行顺序
gcc create.c -o b.out
./b.out //只需运行一次就可,创建共享内存
gcc chat.c -pthread
./a.out
打开新的终端运行./a.out 进行群聊
|