system消息队列

1.创建一个消息队列,向此消息队列发送一个字节的消息,然后调用MSGCTL函数的IPC_STAT.获得消息队列情况,

调用system函数,执行ipcs -q命令,

最后删除此消息队列;

 

2.用ftok函数创建一个消息队列,有排他性选项;

  1)  int flag=IPC_MODE|IPC_CREAT;//用int存放这些标示

 

  2)switch(c)
            {
                case 'e'://是'e'不是"e"

 

 3)    key=ftok(argv[optind],0);//optind用法以及ftok函数

 

3.创建一个专门发送消息的程序

 

 1) struct msgbuf *msgptr;/*如何用结构体指针*/

      msgptr=calloc(.....)

 

 2)byte=atoi(argv[2]); /*把入参传给int类型时,要用atoi*/

 

 3)msgptr->mtype=type;//指针要用->,不是.

 

4.接受,

5删除队列的

 

6创建一个文件做标识符,传给一个接受消息的程序

  1)  if(optind!=2)// 不知道用optind什么效果 ,optind 始终为1,所以不可以当判断条件

  2)msgid=atoi(argv[1]);//msgid=argv[1]; 入参一定转换

  3)buf=malloc(MAXSIZE);//要记得给结构体分配大小

  4)type = %ld",n,buf->mtype);//struct msgbuf 中的mtype是long型

 

7.完成一个客户服务端的例子,用两个消息队列;

 1)由windows写好的makefile传到服务器上,执行make命令,有时候会报错,stop。。。之类的,这时候,直接在后台

用vi建立makefile就可以

 

2)服务端:

 

定义一个结构体

struct A{

         ....

            }AA

 

定义结构体变量,struct A  myA; 

这里不可以用struct  AA  myA;会报错error #2070: incomplete type is not allowed

 

给结构体指针分配空间

struct A  *pmyA;<-这里是指针不是对象

pmyA=calloc(...);

 

结构体对象,调用其内部成员 myA.成员名

结构体指针,调用其内部成员pmyA->成员名

注意.与->

 

 

使用fopen 或者 open

FILE *fd;//int fd; fopen返回FILE *,所以不可以用inr类型

int     fd;//open返回int型

 

fopen与fgets配合,open与read配合;

 

  if( (fd=fopen(buf.msg,"r")) ==0 )

//fopen(buf.msg,"r")  不可以为fopen(buf.msg,O_RDONLY), O_RDONLY用于open
 if( (fd=open(buf.msg,O_RDONLY)) <0 )

 

 while(fgets(buf.msg,MAXSIZE,fd)!=0)//每次取一行

 while( (n=read(fd,buf.msg,MAXSIZE))!=0 ) //把文件内容全部取出

 

//fgets会在字符串末尾加上/n结束,调用msgsnd的时候还要去'/n'

 

消息结构体中的类型一定要赋值

buf.mtype=MSGTYPE;  //如果不赋值类型,就无法发送出去,msgsnd返回-1

 

函数结尾要关闭文件描述符

 

 

 

msgsnd 与 msgrcv

n=msgrcv(readfd,&buf,MAXSIZE,MSGTYPE,0)) ==0 )// n为客户msgsnd的第三个参数,不是MAXSIZE

 

msgsnd(writefd,&buf,n,0);//msgsnd的第三个参数不是消息最大字节数,而是要发送的消息大小,不加结构体的类型的大小

 

客户端与服务端的msgsnd 成功后都返回的0,不是发送的字节;

服务端的msgrcv 成功后返回客户端发送过来的数据的大小,而客户端的 msgrcv却只返回1;

 

 

 

while( (rcvlen=msgrcv( ...)>0) )
{
   
    //printf("%s/n",buf.msg);   // 用printf可以全部打印出来,而用write只输出一个字符,难道是第三个参数rcvlen的原因,因为,每次rcvlen返回是1;;最后发现,输出msgrcv的内容时,不用msgrcv的返回值长度,而用strlen(buf.msg)


     //write(1,buf.msg,rcvlen);
    write(1,buf.msg,strlen(buf.msg));
 
}

 

8.复用消息

复用消息就是说了两个特性:

一是V队列不用先进先出,与管道和fifo不一样;

二是用消息类型可以标识消息是哪个进程发送的,所以,进程调用msgrcv的时候,第三个参数用进程号+100;

 

9.复用消息例子

一个服务器,两个客户,一个消息队列;

客户把进程ID传给服务端,服务端返回内容的时候,将ID放入type;客户端接收相应类型的消息;

类型1是客户到服务端的消息类型;

 

缺陷:有死锁的存在,因为多个客户和一个服务端这种模型,是存在死锁的

 

 

vim:远程目录,%创建新文件

 

msgrcv,msgsnd 都在一个循环中,do while 或者 for

 

服务器端:

 

1)msgsrv接收的过来命令的形式是:pid pathname

注意:字符串末尾没有'/n',所以接受到字符串以后要加'/n';

 

2)当消息队列没有消息时,msgsrv返回0,在跳到循环头;

 

3)'/n'与'/0'区别

 

4)msgbuf.mtext[n]='/n';错,如果以这种方式结尾,则用open( msgbuf.mtext,O_RDONLY )时,会报-1错误

     msgbuf.mtext[n]='/0';正确,

 

 

//这里用的是消息队列返回的值n,有的系统上msgrcv成功返回为1,而不是消息的大小,所以,也可以用n=strlen(msgbuf.mtex),msgbuf.mtext[n]='/n'

 

5)if(  (pos=strchr(msgbuf.mtext," ")) ==0)//strchr与strstr函数,两者都返回地址,strchr第二个参数是int,strstr第二个参数是char*,注意,如果找空格,第二个参数应该为" ",而不是' '

 

HP下面的警告:

 a value of type "int" cannot be
          assigned to an entity of type "char *"

 

6)*pos++=0;

//为什么不是*pos=0; 因为*pos++=0 就是(*pos)=0;pos++,为了atol做处理,并且使pos指向了pathnam

 

7)atol(msgbuf.mtext);//atol跳过前面空格,直到遇到'/0

 

8)while( (n=read(fd,msgbuf.mtext,MAXDATE)>0) )

//第三个参数是指定的文件的大小,但是这个大小是不确定的,第二个参数是个buf,但是这个buf能不能是之前用的消息队列结构体的buf

9) if( (n=msgsnd(msgid,&msgbuf,n,0))==-1 )//msgsnd返回-1是错误

 

 

客户端:

1)

char *ptr;

//定义一个ptr指针,用这个指针指向消息缓冲区,将pid和pathname放入消息缓冲区

 

ptr=mbuf.mtext+len;//ptr指向mtext末尾

 

2)snprintf函数用法

 

3)

if((fptr=fgets(ptr,MAXDATE-len,stdin))==0 && ferror(stdin)) 

//通过ptr指针,对mbuf.mtext进行操作
//如果第三个参数为0,就会出core,必须引用stdlib.h,用stdin

 

//对返回时char *函数的处理
//stdin =0 ,stdout=1在哪个头文件?stdlib.

//fgets会对字符串尾加'/n'

 

4)

write(1,mbuf.mtext,n)

第一个参数用1,而用stdout则报错,这点奇怪

 

 

9.复用消息例子(多子进程)

1)在使用msgget(key,MODE)如果没定义下面权限

 

#define MODE MSG_R|MSG_W|MSG_R>>3|MSG_W>>3|MSG_R>>6|MSG_W>>6|IPC_CREAT
//如果没有上面的权限 消息队列会有异常内容mbuf.mdat=p

 

2)

if( (pos=strstr(mbuf.mdate," "))==NULL)//不用strchr,因为其第二个参数为int,

如果使用了strchr

这里会出core

*pos++=0;//这里出core

 

3)

//char * 的用法,指向数组的末尾

char *pos;
len=strlen(cbuf.mdate);
pos=cbuf.mdate+len;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值