zoukankan      html  css  js  c++  java
  • linux网络编程之system v消息队列(二)

    今天继续学习system v消息队列,主要是学习两个函数的使用,开始进入正题:

    下面则开始用代码来使用一下该发送函数:

    在运行之前,先查看一下1234消息队列是否已经创建:

    用上次编写的查看消息队列状态的程序来查看一下此时的状态:

    接下来运行发送消息程序:

    接下来再来发送一个消息:

    目前发送的字节总数为300,还没有超过最大字节数msgmnb=16384,下面来看下如果超过了这个字节数,会怎么样?所以继续发送消息:

    这是由于每条消息最大长度是有上限的(MSGMAX),它的上线就等于8192:

    这已经在上节中介绍过,所以,将上面的8193改为8192,就不会发送失败了,如下:

    发送这时阻塞了,这是由于原有的消息队列中的总字节数8492+要发送的8192已经大于16384(消息队列总的字节数),默认就会阻塞,也就是发送还是没成功,查看一下状态既可知道:

    这时可以指定一个发送选项来更改阻塞行为:

    这时看效果:

    可见就不会阻塞了,返回EAGAIN错误了。

    相对发送函数,接收函数要比它复杂一些,先认识一下它:

    其中最主要是要了解第四个参数,msgtyp,如下:

    下面用程序来验证下,在运行这个程序时,可以这样使用:

    要实现这样的功能,需要用到getopt函数,所以首先需要通过该函数来解析命令参数,下面先来熟悉一下该函数,其实不是太难:

    下面运行一下:

    下面来解析-n-t选项,修改代码如下:

    编译运行:

    关于getopt函数的使用基本就这些,还是比较简单,下面则正式开始编写消息的接收功能:

    msg_recv.c:

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    
    #define ERR_EXIT(m) 
            do 
            { 
                    perror(m); 
                    exit(EXIT_FAILURE); 
            } while(0)
    

     struct msgbuf {
       long mtype; /* message type, must be > 0 */
       char mtext[1]; /* message data */
     };

    #define MSGMAX 8192//定义一个宏,表示一条消息的最大字节数
    int main(int argc, char *argv[])
    {
        int flag = 0;
        int type = 0;
        int opt;
    
        while (1)
        {
            opt = getopt(argc, argv, "nt:");
            if (opt == '?')
                exit(EXIT_FAILURE);
    
            if (opt == -1)
                break;
            
            switch (opt)
            {
            case 'n':
                /*printf("AAAA
    ");*/
                flag |= IPC_NOWAIT;
                break;
            case 't':
                /*
                printf("BBBB
    ");
                int n = atoi(optarg);
                printf("n=%d
    ", n);
                */
                type = atoi(optarg);
                break;
            }
        }
    
        int msgid;
        msgid = msgget(1234, 0);
        if (msgid == -1)
            ERR_EXIT("msgget");
    
        struct msgbuf *ptr;
        ptr = (struct msgbuf*)malloc(sizeof(long) + MSGMAX);
        ptr->mtype = type;
        int n = 0;
        if ((n = msgrcv(msgid, ptr, MSGMAX, type, flag)) < 0)//接收消息
            ERR_EXIT("msgsnd");
    
        printf("read %d bytes type=%ld
    ", n, ptr->mtype);
    
        return 0;
    }

    运行:

    接下来接收消息:

    下面再来发送一些消息:

    下面来验证一下当消息类型为负数时的情况,先清空消息:

    当消息类型为负时,还有一个特点,如下:

    下面来验证一下,重新发送几个消息,并来分析接收的顺序:

    下面还有一些规则:

    默认情况下每条消息最大长度是有上限的(MSGMAX),它的上线就等于8192,当发送消息超过这个大小时,则会报错,上面也已经论证过:

    但是如果将msgflg设置成MSG_NOERROR,消息超过时,是不会报错的,只是消息会被截断。

    这个很容易就可论证了,这里就不多解释了,消息队列可以按指定的顺序来接收消息,而不按先进先出的原则,这跟管道是不一样的。

    好了,今天学习就到这,下次继续~

  • 相关阅读:
    mysql常用命令
    【转】Hibernate级联注解CascadeType参数详解
    【转】el表达式的判断符
    js中使用进行字符串传参
    【转】HTML5 jQuery图片上传前预览
    Win10家庭版安装Docker Desktop报错:Containers Windows Feature is not available
    采用反射机制,得出属性是否忽略
    Windows 我的常用命令
    数据相关需要注意,工作所遇场景
    引入 QueryDsl 开发步骤
  • 原文地址:https://www.cnblogs.com/webor2006/p/4165995.html
Copyright © 2011-2022 走看看