linux网络编程之system v消息队列(二)

时间:2023-03-09 19:10:10
linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

这时看效果:

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

下面运行一下:

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

编译运行:

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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()

 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 = ;
int type = ;
int opt; while ()
{
opt = getopt(argc, argv, "nt:");
if (opt == '?')
exit(EXIT_FAILURE); if (opt == -)
break; switch (opt)
{
case 'n':
/*printf("AAAA\n");*/
flag |= IPC_NOWAIT;
break;
case 't':
/*
printf("BBBB\n");
int n = atoi(optarg);
printf("n=%d\n", 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", n, ptr->mtype); return ;
}

运行:

linux网络编程之system v消息队列(二)

接下来接收消息:

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

下面再来发送一些消息:

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

下面还有一些规则:

linux网络编程之system v消息队列(二)

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

linux网络编程之system v消息队列(二)

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

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