LINUX进程通信--消息队列

进程通信方式有很多,这里介绍消息队列,首先需要定义消息队列结构体

struct s_msg{
    long type;
    char mtext[BUFSIZE];
}s_msg;

注意这里的第一个成员是必需的,需要是long型,后面的成员不限。


然后建立一个消息队列

if((mid=msgget(LISTID,IPC_CREAT|0666))==-1)
        perr_exit("msgget:");

代码里0666是消息队列的ID号,这要求发送方与接收方的ID是一致的

发送方代码如下:(不完整代码,但封装成一个函数,只需要调用即可)

void Send_msg(char *cmd, long type )
{
	/****************/
   int mid;
   if((mid=msgget(4446,0666))==-1)
	   perr_exit("msgget:");
   char buf[BUFSIZE];
   memset(buf,'\0',BUFSIZE);
   struct s_msg mymsg;

   mymsg.type = type;
   strcpy(mymsg.mtext, cmd);
   if(msgsnd(mid,&mymsg,BUFSIZE,IPC_NOWAIT))      //msgsiz
	   perr_exit("msgsnd:");
	/****************/
}


接收方代码如下:(完整代码,加入的是项目的一些需求,可以对它进行删减的)

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <signal.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>

#define LISTID 4446

#define BUFSIZE 256

#define  QUEUE_LINE  12
#define  SOURCE_PORT 8000
#define  TCP_SEND_LEN   50
#define  SERVER_ADDRESS "172.31.102.12"

struct s_msg{
    long type;
    char mtext[BUFSIZE];
}s_msg;


void perr_exit(const char *s)
{
    perror(s);
    exit(1);
}

void process_info(int s, struct s_msg *p)
{
        int recv_num = 0;
        int send_num;

        char send_buf[TCP_SEND_LEN];
       				
        //sprintf(send_buf,"1\n");
        memcpy(send_buf, p, TCP_SEND_LEN);

       // printf("begin send\n");
        send_num = send(s,send_buf,sizeof(send_buf),0);
        if (send_num < 0)
		{
             perror("send");
             exit(1);
        } 
		else 
		{
            /// printf("send ok\n");
        }
}


int main(void)
{
    int mid;
    int length;
	char cmd[100];
    if((mid=msgget(LISTID,IPC_CREAT|0666))==-1)
        perr_exit("msgget:");
    struct s_msg mymsg;

	int sock_fd,conn_fd;
	int client_len;
	pid_t pid;

	int inet_sock;
	struct ifreq ifr;
	char ip[32];

	inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
	strcpy(ifr.ifr_name, "eth0");
	ioctl(inet_sock, SIOCGIFADDR, &ifr);
	strcpy(ip, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
	printf("myip = %s\n", ip);
	close(inet_sock);

	struct sockaddr_in addr_serv,addr_client;
	sock_fd = socket(AF_INET,SOCK_STREAM,0);///tcp
	if(sock_fd < 0){
			perror("socket");
			exit(1);
	} else {
			printf("sock sucessful\n");
	}

	memset(&addr_serv,0,sizeof(addr_serv));
	addr_serv.sin_family = AF_INET;
	addr_serv.sin_port = htons(SOURCE_PORT);
	addr_serv.sin_addr.s_addr = inet_addr(ip);
	client_len = sizeof(struct sockaddr_in);
	if(bind(sock_fd,(struct sockaddr *)&addr_serv,sizeof(struct sockaddr_in))<0){
			perror("bind");
			exit(1);
	}
	else
	{
			printf("bind sucess\n");
	}

	if (listen(sock_fd,QUEUE_LINE) < 0)
	{
			perror("listen");
			exit(1);
	}
	else
	{
			printf("listen sucessful\n");
	}

	signal(SIGCHLD, SIG_IGN); // ignore child's dead
    while(1)
    {
		if((length = msgrcv(mid,&mymsg,BUFSIZE,0,0))==-1)   //
		{
			perr_exit("msgrcv");
		}

		if(mymsg.type == 1)
		{
			system(mymsg.mtext);
		}
		else if(mymsg.type == 2)
            {
			sleep(3);
			sprintf(cmd,"/mnt/pc/myvenc_2643_udp_osd_config &");
			system(cmd);
            }
            else if(mymsg.type == 3)  tcp send
            {
			 pid = fork();
			 if(0 == pid)//child
			 {
				 printf("begin accept:\n");
				 conn_fd = accept(sock_fd,(struct sockaddr *)&addr_client,&client_len); ///stop here,if nobody to connect
				 if(conn_fd < 0){
						perror("accept");
						_exit(1);
				 }
				 printf("accept a new client,ip:%s\n",inet_ntoa(addr_client.sin_addr));
				 process_info(conn_fd, &mymsg);
				 close(conn_fd);
				 _exit(0);
			 }
			 else//father, there is no thing can let father to do
			 {
			 }
            }
	   	memset(&mymsg,0,sizeof(mymsg));
		printf("in\n");
    }

    return 0;
}
小结:消息队列使用很方便,相对管道通信而言要显得简单些,而且在结构体上可以加入自己的定制的消息,灵活性也很强。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值