利用消息队列实现多进程通信过程.docx
《利用消息队列实现多进程通信过程.docx》由会员分享,可在线阅读,更多相关《利用消息队列实现多进程通信过程.docx(26页珍藏版)》请在冰豆网上搜索。
利用消息队列实现多进程通信过程
成绩:
课程设计报告
课程名称:
Unix课程设计
设计题目:
利用消息队列实现多进程通信过程
姓名:
专业:
网络工程
班级:
学号:
计算机科学与技术学院
网络系
2013年12月30日
一、选题背景
在UNIX程序设计中消息队列是使用频率最高的几个对象之一,它常应用于对等进程间的通
信和客户—服务器之间的通信。
采用消息队列作为货物托运渠道可以弥补以下缺陷:
(1)消息队列是一种先进先出的队列型数据结构,可以保证先送的货物先到达,后送的
货物后到达,避免了插队现象。
(2)消息队列将输出的信息进行了打包处理,这样就可以保证以每个消息为单位进行接收了。
(3)消息队列还可以将货物进行分类服务,标记各种类别的服务,这样就可以根据货物
类别分别出货。
消息队列是IPC对象的一种与同样提供先进先出服务的管道相比,它有如下特点:
(1)消息队列提供了消息的自动拆分功能,同时不能接收两次发送的消息。
(2)消息队列提供了不完全随机读取的服务,引入消息类型后,一个消息队列在逻辑上可以化身为多个不同消息类型的链表,用户可以自主选择接收某条逻辑链表上的消息,而不必依次接收队列的首条消息。
(3)消息队列提供了完全异步的读写服务。
基于以上背景,我们发现利用消息队列实现进程间的通信可以为我们提供方便,也会是通信效率更为提高。
二、设计思路
可以采用客户-服务器结构,其中服务器端实现各个用户的登录并存储相关信息,客户端通过服务器端获取当前登录用户信息,然后各客户进程通过消息队列实现双向通信。
编程实现两个进程间的通信,一个server(服务器)进程,一个client(客户)进程。
在client(客户)进程下选择注册或者登陆。
若是注册,则server(服务器)进程分给该客户一个新的登陆账号。
多个客户的账号存储在register.txt文件中。
若是选择登陆,登陆成功后服务器进程会显示登陆成功,否则显示登陆失败。
登陆后输入你要发送消息的对方的账号,输入账号后,服务器方显示该账号是否合理,如合理,即可实行通信。
三、主要问题的解决方法和关键技术
实现密码格式登录与注册,通过帐号显示用户名,显示发送消息的日期
四、程序流程图
五、原程序清单
//client.c
#include
#include
#include
#include
#include
#include
#include
#include
structmsgbuf{
longtype;
charbuf[1024];
};
structmsgbuf0{
longtype;
pid_tpid;
charusername[48];
charpassword[48];
charnumber[28];
};
voidfunc();
voidregist();//注册
voidpassw();
voidinputpassw(char*P);
voidenter();//登录
voiddata();
voidstol(char*);//加密
voidltos(char*);//解密
structmsgbuf_msgbuf;
structmsgbuf0_msgbuf0,_msgbuf1;
intmsgid,index,flag;
longnumber;
pid_tpid,pid1;
FILE*fpr;
charusername[16],password[16],buf[64],inde[4],flg[4];
voidmain(){//28
pid_tpid=getpid();
if((msgid=msgget(0x4321,0666|IPC_CREAT))<0){
fprintf(stderr,"msgget()failed.\n");
return;
}
fprintf(stderr,"注册pleaseinput'z',登录input'd':
");
scanf("%s",buf);
memset(&_msgbuf0,0,sizeof(_msgbuf0));
if(buf[0]==100){
enter();//登录
}
elseif(buf[0]==122){
regist();//注册
}
}
voidfunc(){
memset(&_msgbuf,0,sizeof(_msgbuf));
_msgbuf.type=atoi(_msgbuf0.username)+100;
while(msgrcv(msgid,&_msgbuf,sizeof(_msgbuf.buf),_msgbuf.type,IPC_NOWAIT)!
=-1){
fprintf(stderr,"%s[receice].\n",_msgbuf);
memset(&_msgbuf,0,sizeof(_msgbuf));
}
//signal(KILL,func);
}
voidregist(){
memset(_msgbuf0.username,0,16);
memset(_msgbuf0.password,0,16);
fprintf(stderr,"pleaseinputusername(注册):
");
scanf("%s",_msgbuf0.username);
getchar();
if(strlen(_msgbuf0.username)<3||strlen(_msgbuf0.username)>16){
fprintf(stderr,"thelengthofusernamecann'tless3(注册)andmore16.\n");
regist();
}
_msgbuf0.pid=getpid();
_msgbuf0.type=2;//查询
stol(_msgbuf0.username);///加密
passw();//密码
_msgbuf0.type=2;
_msgbuf0.pid=getpid();stol(_msgbuf0.password);///加密
fprintf(stderr,"doyouwanttogetanumberforchat:
(y/n)");
if(getchar()=='y'){
msgsnd(msgid,&_msgbuf0,128,0);
memset(&_msgbuf0,0,sizeof(_msgbuf0));
msgrcv(msgid,&_msgbuf0,128,getpid()+10000,0);
ltos(_msgbuf0.number);
fprintf(stderr,"恭喜你获得一个聊天账号:
%s.\n",_msgbuf0.number);
fprintf(stderr,"登录pleaseinput'd':
");
scanf("%s",buf);
if(buf[0]==100){
enter();//登录
}
}
}
voidpassw(){
fprintf(stderr,"pleaseinputpassword(注册):
");
inputpassw(_msgbuf0.password);
//scanf("%s",_msgbuf0.password);
while(strlen(_msgbuf0.password)<3||strlen(_msgbuf0.password)>16){
fprintf(stderr,"thelengthofpasswordcann'tless3(注册)andmore16.\n");
fprintf(stderr,"pleaseinputpassword(注册):
");
inputpassw(_msgbuf0.password);
//scanf("%s",_msgbuf0.password);
}
fprintf(stderr,"pleaseinputpasswordagain(注册):
");
inputpassw(password);
//scanf("%s",password);
if(strcmp(_msgbuf0.password,password)){
memset(_msgbuf0.password,0,49);
memset(password,0,17);
fprintf(stderr,"两次输入的密码不一致,请从新填写信息。
\n");
passw();
}
}
voidenter(){
memset(&_msgbuf0,0,sizeof(_msgbuf0));
fprintf(stderr,"pleaseinputnumber(登录):
");
scanf("%s",_msgbuf0.number);
getchar();
while((strlen(_msgbuf0.number)!
=8)||(atoi(_msgbuf0.number)>)||(atoi(_msgbuf0.number)<)){
fprintf(stderr,"pleaseinputnumber(登录):
");
scanf("%s",_msgbuf0.number);
getchar();
}
fprintf(stderr,"pleaseinputpassword(登录):
");
inputpassw(_msgbuf0.password);
_msgbuf0.type=1;
number=atoi(_msgbuf0.number);
stol(_msgbuf0.number);///加密
stol(_msgbuf0.password);///加密msgsnd(msgid,&_msgbuf0,128,0);
memset(&_msgbuf,0,sizeof(_msgbuf));
msgrcv(msgid,&_msgbuf,sizeof(_msgbuf.buf),number,0);
ltos(_msgbuf.buf);
sscanf(_msgbuf.buf,"%01[^:
]:
%s",buf,username);
if(!
(strcmp(buf,"n"))){
fprintf(stderr,"%s登陆失败.\n.\n",username);
enter();
}
fprintf(stderr,"%s登陆成功.\n.\n",username);
if((pid1=fork())<0){
fprintf(stderr,"fork()failed.\n");
return;
}
if(pid1>0){
data();
}
if(pid1==0){
while
(1){
memset(&_msgbuf,0,sizeof(_msgbuf));
if(msgrcv(msgid,&_msgbuf,sizeof(_msgbuf.buf),number+,MSG_NOERROR)!
=-1){
ltos(_msgbuf.buf);//解密
fprintf(stderr,"\n%s\n\n[send]:
",_msgbuf.buf);
memset(&_msgbuf,0,sizeof(_msgbuf));
}
}
}
}
voiddata(){
longnumber1;
charusername1[16];
structtmwhen;
time_tnow;
while
(1){
fprintf(stderr,"pleaseinput你要发送对方的账号:
");
memset(&_msgbuf1,0,sizeof(_msgbuf1));
scanf("%s",_msgbuf1.number);
while((strlen(_msgbuf1.number)!
=8)||(atoi(_msgbuf1.number)>)||(atoi(_msgbuf1.number)<)||(atoi(_msgbuf1.number)==number)){
fprintf(stderr,"pleaseinputnumberagain:
");
scanf("%s",_msgbuf1.number);
}
_msgbuf1.type=4;
_msgbuf1.pid=getpid();
number1=atoi(_msgbuf1.number);
stol(_msgbuf1.number);///加密
msgsnd(msgid,&_msgbuf1,128,0);
msgrcv(msgid,&_msgbuf,sizeof(_msgbuf.buf),getpid(),MSG_NOERROR);
ltos(_msgbuf.buf);
sscanf(_msgbuf.buf,"%01[^:
]:
%s",buf,username1);
if(!
(strcmp(buf,"y"))){
while
(1){
memset(&_msgbuf,0,sizeof(_msgbuf));
time(&now);
when=*localtime(&now);
fprintf(stderr,"[send%s%02d:
%02d:
%02d%02d,%02d,%04d]:
",username1,when.tm_hour,when.tm_min,when.tm_sec,when.tm_mon+1,when.tm_mday,when.tm_year+1900);
scanf("%s",_msgbuf.buf);
if(!
strcmp(_msgbuf.buf,"switch")){
data();
break;
}
if(!
strcmp(_msgbuf.buf,"exit"))return;
time(&now);
when=*localtime(&now);
sprintf(_msgbuf.buf,"%s:
[receive--%s--%d--%02d:
%02d:
%02d--%02d,%02d,%04d\n\n\n]",_msgbuf.buf,username,number,when.tm_hour,when.tm_min,when.tm_sec,when.tm_mon+1,when.tm_mday,when.tm_year+1900);
stol(_msgbuf.buf);//加密
_msgbuf.type=number1+;
msgsnd(msgid,&_msgbuf,strlen(_msgbuf.buf),0);
}
}
}
}
//加密
voidstol(char*buf){
longi;
charbuf1[1024];
sscanf(buf,"%s",buf1);
memset(buf,0,sizeof(buf));
for(i=0;isprintf(buf,"%s%03d",buf,buf1[i]+456);
}
}
//解密
voidltos(char*buf){
inti,n=strlen(buf);
charbuf1[4],data[1024];
memset(data,0,sizeof(data));
for(i=0;imemset(buf1,0,sizeof(buf1));
sscanf(buf,"%03s%s",buf1,buf);
i=i+3;
sprintf(data,"%s%c",data,atoi(buf1)-456);
}
sprintf(buf,"%s",data);
}
voidinputpassw(char*buf){
structtermiotm_new,tm_old;
intfd=0,c=0;
memset(buf,0,sizeof(buf));
ioctl(fd,TCGETA,&tm_old);
tm_new=tm_old;
tm_new.c_lflag&=~(ECHO|ICANON);//ECHO显示输入字符ICANON使用标准输入模式
ioctl(fd,TCSETA,&tm_new);
while((c=getchar())!
=10){
fprintf(stderr,"*");
sprintf(buf,"%s%c",buf,c);
}
ioctl(fd,TCSETA,&tm_old);
fprintf(stderr,"\n");
}
//Server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
structmsgbuf{
longtype;
charbuf[1024];
};
structmsgbuf0{
longtype;
pid_tpid;
charusername[48];
charpassword[48];
charnumber[28];
};
voidfunc();
voidfunction();
voidstol(char*);//加密
voidltos(char*);//解密
intrand1();//随机产生一个9位数
structmsgbuf_msgbuf;
structmsgbuf0_msgbuf0,_msgbuf1;
structsembuf_buf;
//pthread_tpid;
FILE*fpr,*fpw;
charbuf[64],username[16],password[16],inde[4],flg[4],*p,number[10];
intmsgid,semid,shmid,index=0,flag=0,sum;
pid_tpid,pid_c;
voidmain(){
if((semid=semget(0x1234,2,0666|IPC_CREAT))<0){
fprintf(stderr,"semget()failed.\n");
return;
}
semctl(semid,0,SETVAL,1);
semctl(semid,1,SETVAL,1);
_buf.sem_flg=_buf.sem_flg&~IPC_NOWAIT;
if((shmid=shmget(0x123,4,0666|IPC_CREAT))<0){
fprintf(stderr,"shmget()failed.\n");
return;
}
p=shmat(shmid,0,0);
(*p)=0;
if((msgid=msgget(0x4321,0666|IPC_CREAT))<0){
fprintf(stderr,"msgget()failed.\n");
return;
}
func();
}
voidfunc(){
if(msgrcv(msgid,&_msgbuf0,128,-2,0)!
=-1){
if((pid=fork())<0){
fprintf(stderr,"fork()failed.\n");
return;
}
if(pid==0){
fprintf(stderr,"解密前receive[number]is%s,[username]is%s,[password]is%s.\n",_msgbuf0.number,_msgbuf0.username,_msgbuf0.password);
ltos(_msgbuf0.username);//解密
ltos(_msgbuf0.number);//解密
ltos(_msgbuf0.password);//解密
pid_c=_msgbuf0.pid;
if(_msgbuf0.type==1){
//denglu
function();
}
if(_msgbuf0.type==2){
//zhuce
_buf.sem_num=0;
_buf.sem_op=-1;
semop(semid,&_buf,1);//wait();
if(*p==0){
_buf.sem_num=1;
_buf.sem_op=-1;
semop(semid,&_buf,1);//wait();
}
(*p)++;
_buf.sem_num=0;
_buf.sem_op=1;
semop(semid,&_buf,1);//signal();
if((fpr=fopen("./register.txt","r"))==NULL){
fprintf(stderr,"fopen()failed.\n");
return;
}
memset(buf,0,sizeof(buf));
see();
fclose(fpr);
_buf.sem_num=0;///////////////
_buf.sem_op=-1;
semop(semid,&_buf,1);//wait();
(*p)--;
_buf.sem_num=0;
_buf.sem_op=1;
semop(semid,&_buf,1);//signal();
if(*p==0){
_buf.sem_num=1;
_buf.sem_op=1;
semop(semid,&_buf,1);//signal();
}
_buf.sem_num=1;
_buf.sem_op=-1;
semop(semid,&_buf,1);//wait();