进程通信方式有很多,这里介绍消息队列,首先需要定义消息队列结构体
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;
}
小结:消息队列使用很方便,相对管道通信而言要显得简单些,而且在结构体上可以加入自己的定制的消息,灵活性也很强。