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,消息超过时,是不会报错的,只是消息会被截断。

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

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

原文地址:https://www.cnblogs.com/webor2006/p/4165995.html