首页 > 代码库 > 利用System V消息队列实现回射客户/服务器
利用System V消息队列实现回射客户/服务器
一、介绍
在学习UNIX网络编程 卷1时,我们当时可以利用Socket套接字来实现回射客户/服务器程序,但是Socket编程是存在一些不足的,例如:
1. 服务器必须启动之时,客户端才能连上服务端,并与服务端进行通信;
2. 利用套接口描述符进行通信,必须知道对端的IP与端口。
二、相关函数介绍
下面,我们利用System V消息队列来实现进程间的通信:
首先,我们先来了解一下下面几个函数:
1. msgget: 该函数用于打开或创建消息队列,其作用相当与文件操作函数open。
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int msgflg);
2. msgsnd:消息发送函数
3. msgrcv:消息接收函数
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
4. struct msgbuf
struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */
};
mtype 消息类型
mtext 消息内容
三、实现原理
服务器端:只接收类型为1的消息,接收完毕之后,取出mtext的前四个字节并存储为client_pid,并将消息类型mtype修改为client_pid;
客户端:只发送类型为1的消息,即将 mtype 置为1,并将mtext的前四个字节的内容设为自身的进程id,即pid.
四、编程实现如下:
客户端:
/************************************************************************* > File Name: echocli.c > Author: ma6174 > Mail: ma6174@163.com > Created Time: Tue 28 Oct 2014 11:25:48 AM HKT ************************************************************************/#include<stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdlib.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while(0)#define MSGMAX 8192struct msgbuf{ long mtype; /* type of message */ char mtext[MSGMAX]; /* message text */};void echo_cli(int msgid){ int pid = getpid(); int n; struct msgbuf msg; memset(&msg, 0, sizeof(msg)); msg.mtype = 1; *((int*)msg.mtext) = pid; while(fgets(msg.mtext + 4, MSGMAX, stdin) != NULL) { msg.mtype = 1; if(msgsnd(msgid, &msg, 4 + strlen(msg.mtext + 4), IPC_NOWAIT) < 0) ERR_EXIT("msgsnd"); memset(msg.mtext + 4, 0, MSGMAX - 4); if((n = msgrcv(msgid, &msg, MSGMAX, pid, 0)) < 0) ERR_EXIT("msgrcv"); fputs(msg.mtext + 4, stdout); memset(msg.mtext + 4, 0, MSGMAX - 4); }}int main(int argc, char **argv){ int msgid; msgid = msgget(1234, 0);//open if(msgid == -1) ERR_EXIT("msgget"); echo_cli(msgid); return 0;}
服务端:
/************************************************************************* > File Name: echosrv.c > Author: ma6174 > Mail: ma6174@163.com > Created Time: Tue 28 Oct 2014 11:25:58 AM HKT ************************************************************************/#include<stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdlib.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while(0)#define MSGMAX 8192struct msgbuf{ long mtype; /* type of message */ char mtext[MSGMAX]; /* message text */};void echo_srv(int msgid){ int n; struct msgbuf msg; memset(&msg, 0, sizeof(msg)); while(1) { //only recv the message of type = 1 if((n = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0) { ERR_EXIT("msgrcv"); } fputs(msg.mtext + 4, stdout); //client pid int pid; pid = *((int*)msg.mtext); //回射 msg.mtype = pid;//type msgsnd(msgid, &msg, n, 0); memset(&msg, 0, sizeof(msg)); }}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;}
存在问题:
1. 不同主机间不同的进程无法进行通信。
2. 消息的长度受到限制MSGMAX
3. 消息的数量收到限制MSGMNB
4. 会出现死锁问题。
利用System V消息队列实现回射客户/服务器
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。