system消息队列

    技术2022-05-19  21

    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;

     


    最新回复(0)