消息队列实现回射客户/服务器

msg_srv.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0) #define MSGMAX 8192
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[MSGMAX]; /* message data */
}; void echo_srv(int msgid)
{
int nRec = 0;
struct msgbuf msg; while(1)
{
if( (nRec = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0)
ERR_EXIT("msgsnd"); int pid;
pid = *((int*)msg.mtext);
fputs(msg.mtext+4,stdout);
msg.mtype = pid;
msgsnd(msgid, &msg, nRec, 0);
}
} int main(int argc, char* argv[])
{
int msgid;
msgid = msgget(1234,IPC_CREAT|0666);
if(msgid == -1)
ERR_EXIT("msgget"); printf("msget success, msgid=%d\n",msgid); echo_srv(msgid); return 0;
}

msg_cli.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0) #define MSGMAX 8192
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[MSGMAX]; /* message data */
}; void echo_cli(int msgid)
{
int pid,nRec;
struct msgbuf msg;
memset(&msg, 9, sizeof(msg));
pid = getpid();
*((int*)msg.mtext) = pid; while(fgets(msg.mtext+4, MSGMAX, stdin) != NULL)
{
msg.mtype = 1; if(msgsnd(msgid, &msg, 4+strlen(msg.mtext+4), 0) < 0)
ERR_EXIT("msgsnd"); memset(msg.mtext+4, 0, MSGMAX-4);
if( (nRec = msgrcv(msgid, &msg, MSGMAX, pid, 0)) < 0)
ERR_EXIT("msgsnd"); fputs(msg.mtext+4, stdout);
memset(msg.mtext+4, 0, MSGMAX-4);
} } int main(int argc, char const *argv[])
{
int msgid;
msgid = msgget(1234,0);
if(msgid == -1)
ERR_EXIT("msgget"); echo_cli(msgid); return 0;
}

  当服务器端收到客户端的请求之后,需要向客户端回射数据, 此时服务器端处于往消息队列发送消息的状态;

这时很多客户端发起很多的请求,将队列读满了,此时服务器端发送将阻塞;而客户端也阻塞等待读取数据,这时就产生了死锁

如果使用非阻塞的模式发送,因为队列满了,没有办法往消息队列中填充数据,会返回EAGAIN错误,又迫使服务器再次往消息队列中填充数据,此时客户端依旧无法获取到数据

msg_cli.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0) #define MSGMAX 8192
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[MSGMAX]; /* message data */
}; void echo_cli(int snd_msgid, int rcv_msgid)
{
int pid,nRec;
struct msgbuf msg;
memset(&msg, 9, sizeof(msg));
*((int*)msg.mtext) = rcv_msgid; while(fgets(msg.mtext+4, MSGMAX, stdin) != NULL)
{
msg.mtype = 1; if(msgsnd(snd_msgid, &msg, 4+strlen(msg.mtext+4), 0) < 0)
ERR_EXIT("msgsnd"); sleep(1);
memset(msg.mtext+4, 0, MSGMAX-4);
if( (nRec = msgrcv(rcv_msgid, &msg, MSGMAX, 2, 0)) < 0)
ERR_EXIT("msgrcv"); fputs(msg.mtext+4, stdout);
memset(msg.mtext+4, 0, MSGMAX-4);
} } int main(int argc, char const *argv[])
{ int snd_msgid, rcv_msgid;
snd_msgid = msgget(1234,0);
rcv_msgid = msgget(IPC_PRIVATE,0666);
if(snd_msgid == -1 || rcv_msgid == -1)
ERR_EXIT("msgget"); echo_cli(snd_msgid,rcv_msgid); return 0;
}

msg_srv.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0) #define MSGMAX 8192
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[MSGMAX]; /* message data */
}; void echo_srv(int msgid)
{
int nRec = 0;
pid_t pid;
struct msgbuf msg; while(1)
{
if( (nRec = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0)
ERR_EXIT("msgsnd"); fputs(msg.mtext+4,stdout); pid = fork();
if(pid == 0)
{
int nSnd;
int rcv_msgid;
rcv_msgid = *((int*)msg.mtext); msg.mtype = 2;
nSnd = msgsnd(rcv_msgid, &msg, nRec, 0);
if(nSnd == -1)
{
perror("msgsnd");
}
}
}
} int main(int argc, char* argv[])
{
int msgid;
msgid = msgget(1234,IPC_CREAT|0666);
if(msgid == -1)
ERR_EXIT("msgget"); echo_srv(msgid); return 0;
}

第二十七章 system v消息队列(三)的更多相关文章

  1. 第二十五章 system v消息队列(一)

    IPC对象的持续性 随进程持续 :一直存在直到打开的最后一个进程结束.(如pipe和FIFO) 随内核持续 :一直存在直到内核自举(内核自举就是把主引导记录加载到内存,并跳转执行这段内存)或显示删除( ...

  2. 第6章 System V消息队列

    6.1 概述 System V消息队列在内核中是list存放的,头结点中有2个指针msg_first 和msg_last.其中每个节点包含:下个节点地址的指针.类型.长度.数据等. 6.2 函数 6. ...

  3. 第二十六章 system v消息队列(二)

    msgsnd int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 作用: 把一条消息添加到消息队列中 参数: msqi ...

  4. 进程间通信 System V 消息队列

    1.msgget (key_t ket,int flag) ; //创建一个新的消息队列或者访问一个已存在的消息队列 2.msgsnd(int msid, const void *ptr ,size_ ...

  5. Linux进程通信之System V消息队列

    System V消息队列是Open Group定义的XSI,不属于POSIX标准.System V IPC的历史相对很早,在上个世70年代后期有贝尔实验室的分支机构开发,80年代加入System V的 ...

  6. 利用System V消息队列实现回射客户/服务器

    一.介绍 在学习UNIX网络编程 卷1时,我们当时可以利用Socket套接字来实现回射客户/服务器程序,但是Socket编程是存在一些不足的,例如: 1. 服务器必须启动之时,客户端才能连上服务端,并 ...

  7. UNIX环境高级编程——system V消息队列

    unix早期通信机制中的信号能够传送的信息量有限,管道则只能传送无格式字节流,这远远是不够的.     消息队列(也叫报文队列)客服了这些缺点:     消息队列就是一个消息的链表.     可以把消 ...

  8. linux c编程:System V消息队列一

    消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识.具有足 够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息.在某个进 ...

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

    今天继续学习system v消息队列,主要是学习两个函数的使用,开始进入正题: 下面则开始用代码来使用一下该发送函数: 在运行之前,先查看一下1234消息队列是否已经创建: 用上次编写的查看消息队列状 ...

随机推荐

  1. bugku—Web_Writeup

    Bugku_Web_Writeup Writeup略显粗糙~~ 部分Web题没有得到最后的flag~只是有了一个简单的思路~~ Web1: 如上,打开题目答题网址后就会弹出一张图片,看图片就可以发现是 ...

  2. 什么是VR中的Locomotion?

    Locomotion,本文中我称之为移位,是VR研究中最重要的话题之一.因为它属于VR中三大元老级操作(Selection选择,Manipulation操纵物体,Locomotion移位),其中,前两 ...

  3. 基于Docker和Golang搭建Web服务器

    1 场景描述 基于centos7的docker镜像搭建golang开发环境 在docker容器内,使用golang实现一个Web服务器 启动docker容器,并在容器内启动Web服务器 我购买了一个最 ...

  4. 《完美解决系列》Android5.0以上 Implicit intents with startService are not safe

    在Android6.0上,使用了以下代码: Intent intent = new Intent(); intent.setAction("xxx.server"); bindSe ...

  5. 服务器时间误差导致的google sign-in后台验证错误(远程调试java程序)

    https://developers.google.com/identity/sign-in/web/backend-auth import com.google.api.client.googlea ...

  6. 关于Git的使用方法

    1.查看Git的使用方法 : git 2.把当前文件夹变为一个git仓库 创建git仓库:git init 3.查看当前仓库文件变化情况:git status 4.添加修改:git add (可使用g ...

  7. SpringCloud-动态配置变化监控-获取变化(支持Config、Nacos)

    SpringCloud-动态配置变化监控-获取变化(支持Config.Nacos) qq交流群: 812321371 微信交流群: MercyYao 简介 配置中心有原生的 SpringCloud C ...

  8. python 基本排序算法

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/9/15 下午5:06 # @Author : lb # @File : so ...

  9. Java工程师学习指南(中级篇)

    Java工程师学习指南 中级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我写的文章都是站 ...

  10. Django-admin站点管理的详细使用

    使用Django的管理模块,需要按照如下步骤操作: 管理界面本地化 创建管理员 注册模型类 自定义管理页面 1 管理界面本地化 在settings.py中设置语言和时区 LANGUAGE_CODE = ...