基于多进程QQ聊天软件设计Word文档格式.docx
- 文档编号:17377653
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:15
- 大小:118.48KB
基于多进程QQ聊天软件设计Word文档格式.docx
《基于多进程QQ聊天软件设计Word文档格式.docx》由会员分享,可在线阅读,更多相关《基于多进程QQ聊天软件设计Word文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
structmsg_server{//消息结构体
longmytype;
//消息类型,我用的是发送消息的进程号
intmy_msgid;
//客户端的私有消息队列号
charmyname[10];
//客户端用户姓名
charaim_name[10];
//此条消息将要发送的对象
chartext[BUFSIZ];
//消息正文
structmsg_server*next;
//链表节点连接指针
/*
structmsg_land{
inttype;
intpid;
intmsgid;
charname[10];
structmsg_chat{
*/
#endif
/*服务器*/
#include"
include.h"
staticintpid;
//进程号
staticstructmsg_server*Lp;
//测试用的
staticintlen;
//消息长度
staticstructmsg_serverbuf;
//父进程向子进程通过管道发送消息的缓冲区
staticstructmsg_serverbuf_c;
//子进程通过管道接收消息缓存区
staticstructmsg_server*ps;
staticstructmsg_servermsg_rcv;
//父进程通过消息队列接收消息缓存区
staticstructmsg_server*L;
staticstructmsg_server*Q;
staticintcom_qid;
//公共消息队列号
staticintflag;
//判断是不是登陆信息的标志
staticstructmsg_server*tmp;
//用于遍历的临时结构体循环变量
statickey_tkey;
staticintpfd[2];
//用于管道通信的文件标识符
staticstructmsg_server*H;
//众所周知的消息队列链表头
staticcharoffline[]="
对不起,您找的用户不在线.\n请输入quit重新选择聊天对象\n"
;
/*SIGINT信号处理,删除消息队列,关闭管道文件*/
voidmy_func(intsign_no)
if(sign_no==SIGINT){
if(msgctl(com_qid,IPC_RMID,NULL)<
0){
perror("
msgctl"
);
exit
(1);
}
close(pfd[0]);
close(pfd[1]);
_exit
(1);
}
/*退出处理函数入退出栈*/
voidmy_exit(void)
/*消息结构体进入链表*/
intget_in(structmsg_server*L,structmsg_servermsg_rcv)
intflag=0;
//判断是不是新登录用户
structmsg_server*new_node;
while
(1){
if(L->
mytype==msg_rcv.mytype){//若找到属于本用户的结点
strncpy(L->
text,msg_rcv.text,strlen(msg_rcv.text));
//将消息放入链表结点文本区(覆盖)
break;
}
next==NULL){//若新用户,则创建新结点
new_node=(structmsg_server*)malloc(sizeof(structmsg_server));
new_node->
next=NULL;
mytype=msg_rcv.mytype;
my_msgid=msg_rcv.my_msgid;
strcpy(new_node->
myname,msg_rcv.myname);
aim_name,msg_rcv.aim_name);
text,msg_rcv.text);
L->
next=new_node;
flag=1;
//flag==1时,为新用户登录
L=L->
next;
//遍历链表
returnflag;
/*根据收到消息查找要发送的对象*/
structmsg_server*find(structmsg_server*L,structmsg_serverM)
structmsg_server*F;
F=L;
if(F!
=NULL){
while((F!
=NULL)&
&
(strcmp(F->
myname,M.aim_name))){//若找到,则退出while
F=F->
//printf("
F->
name:
%s\nM.aim_name:
%s"
F->
myname,M.aim_name);
}
if(NULL==F){//找不到,则提示用户不在线,向发送消息的用户发送本消息
strcpy(M.text,offline);
len=sizeof(long)+sizeof(int)+20+strlen(M.text);
if((msgsnd(M.my_msgid,&
M,len-1,0))<
0){
perror("
msgsnd"
exit
(1);
}
returnNULL;
//聊天对象不在线,返回空指针
elsereturnF;
//在线,定位聊天对象
else{
printf("
nomessage!
\n"
}
intmain(void)
signal(SIGINT,my_func);
//调用SIGINT信号处理函数
atexit(my_exit);
//退出处理函数
H=(structmsg_server*)malloc(sizeof(structmsg_server));
//建立头结点
H->
next=NULL;
mytype=-1;
if(pipe(pfd)<
0){//建立无名管道(用于父子进程通信)
perror("
pipe"
exit
(1);
printf("
服务器正在运行......\n"
(按ctrl+c结束运行,请确保各客户端先退出)\n"
if((pid=fork())<
fork"
/*子进程负责私聊时给对应客户端发送消息*/
if(pid==0){
//printf("
thisischildprocess!
close(pfd[1]);
read(pfd[0],&
buf_c,sizeof(buf_c));
//从管道里读父进程发来的数据,为服务器最新收到的私聊消息
childtomsgid:
%d\n"
buf_c.my_msgid);
thechildprocesstext:
%s\n"
buf_c.text);
len=sizeof(long)+sizeof(int)+20+strlen(buf_c.text);
if((msgsnd(buf_c.my_msgid,&
buf_c,len-1,0))<
perror("
exit
(1);
}//endif
usleep(300000);
//延时
/*父进程负责接收客户端发来的消息,另外群聊消息也有父进程负责*/
if(pid>
0){
close(pfd[0]);
thisisparentprocess!
if(-1==(key=ftok("
."
'
x'
))){
ftok"
if((com_qid=msgget(key,IPC_CREAT|0666))==-1){//创建众所周知的消息队列
msgget"
while
(1){//进入读写循环
//printf("
thereinwhile
(1)\n"
if(msgrcv(com_qid,(void*)&
msg_rcv,sizeof(msg_rcv),0,0)<
0){//接收客户端发来的消息(结构体)
msgrcv"
if(strncmp(msg_rcv.text,"
quit"
4)){//判断是否为正常消息
flag=get_in(H,msg_rcv);
//入消息队列结构体链表
/*Lp=H->
while(Lp!
=NULL){
mytype:
%ld\n"
Lp->
mytype);
my_msgid:
my_msgid);
myname:
myname);
othername:
aim_name);
thetext:
text);
Lp=Lp->
if(flag==0){//flag==0正常消息,非登陆信息
if((strncmp(msg_rcv.aim_name,"
all"
3)==0)&
(strlen(msg_rcv.text)>
0)){//判断是否为群聊
tmp=H->
len=sizeof(long)+sizeof(int)+20+strlen(msg_rcv.text);
while(tmp!
if(tmp->
mytype!
=msg_rcv.mytype){
if((msgsnd(tmp->
my_msgid,&
msg_rcv,len-1,0))<
perror("
exit
(1);
}
}
tmp=tmp->
//群聊遍历发送
}//endwhile
}else{//非群聊,交给子进程
ps=find(H,msg_rcv);
//定位聊天对象
if(ps!
/*printf("
ps:
\nmytype:
ps->
printf("
buf.mytype=msg_rcv.mytype;
strcpy(buf.myname,msg_rcv.myname);
strcpy(buf.aim_name,msg_rcv.aim_name);
strcpy(buf.text,msg_rcv.text);
buf.my_msgid=ps->
my_msgid;
write(pfd[1],&
buf,sizeof(buf));
//向管道中写入数据,有子进程接收
}//endifps
}//endelse
}//endifflag
usleep(300000);
}//endif
}//endwhile
return0;
/*客户端*/
time_ttd;
structtm*tm_p;
//用于获取时间
intprivate_qid;
//私有消息队列号
intcom_qid;
//众所周知的消息队列号
charch;
staticstructmsg_servermymsg;
//将要发送的消息的缓冲结构体
memset(mymsg.text,'
\0'
BUFSIZ);
//将正文初始化,以便服务器判断是登陆信息还是聊天信息
structmsg_servermsg_rcv;
//接收消息缓冲区
*************欢迎使用*************\n"
(输入'
quit'
退出,群聊请将聊天对象设为'
all'
)\n"
温馨提示:
请确保服务器正在运行。
-----------请输入登录信息---------\n"
您的用户名:
"
scanf("
mymsg.myname);
intlen;
//发送消息的总长度
pid_tpid;
key_tkey;
/*建立私有消息队列*/
if((private_qid=msgget(IPC_PRIVATE,IPC_CREAT|0666))<
/*创建子进程*/
/*进入父进程*/
))){
/*创建或打开众所周知的消息队列*/
if((com_qid=msgget(key,IPC_CREAT|0666))==-1){
mymsg.my_msgid=private_qid;
//发送使用消息队列号
start:
想与谁对话:
//goto语句
scanf("
mymsg.aim_name);
printf("
====****====StartChat====***====\n"
do{
if(fgets(mymsg.text,BUFSIZ,stdin)==NULL){//获取键盘输入
fgets"
mymsg.mytype=getpid();
//将消息类型设为进程号
/*printf("
mymsg.mytype);
mymsg.my_msgid);
mymsg.text);
len=sizeof(long)+sizeof(int)+20+strlen(mymsg.text);
//求出消息长度
if((msgsnd(com_qid,&
mymsg,len-1,0))==-1){//发送消息
if(strlen(mymsg.text)>
1)//排除第一次输出(若为登陆信息,则不打印)
---------------------------------\n"
请输入:
//提示语
}while(strncmp(mymsg.text,"
4));
//当用户输入‘quit’时返回
您确定要退出么?
\n(y:
确认退出;
n:
重新选择聊天对象)\n"
%c"
&
ch);
//获取用户选择
if(ch=='
n'
)
gotostart;
//返回
else{//退出
谢谢您的使用!
————QQByliaoye\n"
if((msgctl(private_qid,IPC_RMID,NULL))<
0){//删除消息队列
/*进入子进程*/
while
(1){
//memset(msg_rcv,0,BUFSIZ);
if((msgrcv(private_qid,&
msg_rcv,sizeof(msg_rcv),0,0))<
0){//服务器发来的接收消息
time(&
td);
//获取日历时间
tm_p=localtime(&
//转换为本地时间
\n*********%d年%d月%d日*********\n"
1900+tm_p->
tm_year,1+tm_p->
tm_mon,tm_p->
tm_mday);
消息来自<
%s>
\t"
msg_rcv.myname);
--%d:
%d:
tm_p->
tm_hour,tm_p->
tm_min,tm_p->
tm_sec);
--------------------------------\n"
%s\t:
msg_rcv.myname,msg_rcv.text);
//输出
/***********OVER***************************/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 进程 QQ 聊天 软件设计