用socket(基于tcp协议)进行本地间多进程通信
本地进程:ipc server为服务端,维护一组连接进来的客户端socket fd,把每个客户端发过来的数据判断是服务器已经订阅的消息就分发到全部连接进来的客户端.
本地进程:ipc client1为客户端1,客户端1连接服务端,并接受服务端分发的数据,判断该数据是否是自己需要的数据(订阅的数据),如果是就做出处理,否则扔掉.
本地进程:ipc client2为客户端2,客户端2连接服务端,并接受服务端分发的数据,判断该数据是否是自己需要的数据(订阅的数据),如果是就做出处理,否则扔掉.
本地进程:ipc client3为客户端3,客户端3连接服务端,并接受服务端分发的数据,判断该数据是否是自己需要的数据(订阅的数据),如果是就做出处理,否则扔掉.
......
客户端1与客户端3需要通信,则客户端1需要先订阅客户端3有关信息,客户端3发布数据(包含客户端1订阅的有关信息)到ipc server,ipc server分发到所有客户端,客户端1收到数据,判断数据,发现是已订阅客户端3的有关信息,做出相应处理.客户端2没有订阅,则扔掉数据.
......
其他客户端用类似方式进行进程通信,订阅的信息可以作为数据头拼接进数据包,客户端收到分发的数据,解析出数据头并与订阅信息比较,调用函数处理.
(server可以将消息类型与数据都分发到客户端,客户端根据消息类型,如果是已订阅消息类型就将数据(包含消息类型)传到一个回调函数,回调函数根据消息类型进行处理.代码未实现)
代码实现(由于时间原因,写得比较简陋与粗糙):
ipc server端:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<sys/socket.h>
5 #include<netinet/in.h>
6 #include<arpa/inet.h>
7 #include<unistd.h>
8 #include<pthread.h>
9 #include<sys/select.h>
10 #include<sys/time.h>
11 #include<vector>
12 using namespace std;
13 vector<int>sockfds;
14 vector<int>subscribes;
15 int my_sock_fd;
16 pthread_mutex_t mtx;
17 void* read_thread(void *arg);
18 void read_run(int sockfd);
19 void read_run(int sockfd)
20 {
21 pthread_t thread;
22 my_sock_fd=sockfd;
23 if(pthread_create(&thread, NULL,read_thread, NULL)!=0)//创建子线程
24 {
25 perror("pthread_create error");
26 }
27 else
28 {
29 printf("pthread_create success\n");
30 }
31 }
32 void* read_thread(void *arg)
33 {
34 int sock_fd=my_sock_fd;
35 printf("read_thread sock_fds:%d\n",sock_fd);
36 while(1)
37 {
38 char buf[100] = {0};
39 int ret=-1;
40
41 ret = read(sock_fd,buf,sizeof(buf));
42 if(ret>0)
43 {
44 printf("接受了%d字节,内容:%s\n",ret,buf);
45 if(buf[0]=='%'&&buf[1]=='%')//订阅消息
46 {
47 bool pushsub=true;
48 printf("client subscribe msg is:[%c]\n",buf[2]);
49 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
50 {
51 if(*it==buf[2])
52 {
53 pushsub=false;
54 }
55 }
56 if(pushsub==true)
57 subscribes.push_back(((int)buf[2]));
58 printf("all subscribes msg:\n");
59 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
60 {
61 printf("[%c] ",*it);
62 }
63 printf("\n");
64 }
65 else if(buf[0]=='$'&&buf[1]=='$')//取消订阅消息
66 {
67 printf("client cancel subscribe msg is:");
68 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
69 {
70 if(*it==buf[2])
71 {
72 printf("[%c]\n",*it);
73 subscribes.erase(it);
74 break;
75 }
76 }
77 printf("all subscribes msg:");
78 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
79 {
80 printf("[%c] ",*it);
81 }
82 printf("\n");
83 }
84 else
85 {
86 for(vector<int>::iterator sit=subscribes.begin();sit!=subscribes.end();sit++)//分发消息
87 {
88 if(*sit==buf[0])
89 {
90 for(vector<int>::iterator it=sockfds.begin();it!=sockfds.end();it++)
91 {
92 printf("write sock_fds:%d\n",*it);
93 int res=write(*it,buf,99);
94 printf("write %d byte\n",res);
95 }
96 }
97
98 }
99 }
100
101 }
102 if(ret==0)
103 {
104 for(vector<int>::iterator it=sockfds.begin();it!=sockfds.end();it++)
105 {
106 if(*it==sock_fd)
107 {
108 pthread_mutex_lock(&mtx);
109 printf("close sock_fds:%d\n",sock_fd);
110 sockfds.erase(it);
111 close(sock_fd);
112 pthread_mutex_unlock(&mtx);
113 break;
114 }
115 }
116 printf("after erase all sock_fds: ");
117 for(vector<int>::iterator it=sockfds.begin();it!=sockfds.end();++it)
118 {
119 printf("%d ",*it);
120 }
121 printf("\n");
122 break;
123 }
124 }
125 }
126 int main()
127 {
128 pthread_mutex_init(&mtx, NULL);
129 int sockfd = socket(AF_INET,SOCK_STREAM,0);
130 if (sockfd == -1)
131 {
132 perror("socket"),exit(-1);
133 }
134 for(int i='a';i<='b';i++)//默认订阅消息[a]与[b]
135 subscribes.push_back(i);
136 struct sockaddr_in addr;
137 addr.sin_family = AF_INET;
138 addr.sin_port = htons(12222);
139 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
140 int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
141 if (res == -1)
142 {
143 perror("bind\n");
144 exit(-1);
145 }
146 printf("bind ok\nwait client connect...\n");
147 listen(sockfd,100);//监听
148 struct sockaddr_in client;
149 socklen_t len = sizeof(client);
150 printf("input [exit] and press Ctrl+C exit this program\n");
151 while(1)
152 {
153 int fd = accept(sockfd,(struct sockaddr*)&client,&len);
154 char *from = inet_ntoa(client.sin_addr);//十六进制转点分十进制
155 printf("%s is connected\n",from);
156 pthread_mutex_lock(&mtx);
157 sockfds.push_back(fd);
158 pthread_mutex_unlock(&mtx);
159 printf("sock_fds.push_back:%d\n",fd);
160 read_run(fd);
161 printf("after accept all sock_fds:");
162 for(vector<int>::iterator it=sockfds.begin();it!=sockfds.end();++it)
163 {
164 printf("%d ",*it);
165 }
166 printf("\n");
167 }
168 close(sockfd);
169 return 0;
170 }
ipc client端:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/socket.h>
6 #include<netinet/in.h>
7 #include<arpa/inet.h>
8 #include<pthread.h>
9 #include<vector>
10 bool exit_thread=false;
11 int sockfd ;
12 using namespace std;
13 vector<int>subscribes;
14 void read_run();
15 void* read_thread(void* arg);
16 void read_run()
17 {
18 pthread_t thread;
19 if(pthread_create(&thread, NULL,read_thread, NULL)!=0)
20 {
21 perror("pthread_create error");
22 }
23 else
24 {
25 printf("pthread_create \n");
26 }
27 }
28 void* read_thread(void *arg)
29 {
30 while(1)
31 {
32 if(exit_thread==true)
33 {
34 break;
35 }
36 char buf[100] = {0};
37 int ret=-1;
38 ret = read(sockfd,buf,sizeof(buf));
39 if(ret>0)
40 {
41 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
42 {
43 if(*it==buf[0])
44 {
45 char tmp[99];
46 memcpy(tmp,buf+1,99);
47 printf("接受了%d字节,内容:%s\n",ret-1,tmp);
48 }
49 }
50
51 }
52 }
53 }
54 int main(){
55 sockfd = socket(AF_INET,SOCK_STREAM,0);
56 if (sockfd == -1){
57 perror("socket"),exit(-1);
58 }
59 int i;
60 for(i='a';i<='b';i++)//默认订阅消息[a]与[b]
61 subscribes.push_back(i);
62 struct sockaddr_in addr;
63 addr.sin_family = AF_INET;
64 addr.sin_port = htons(12222);
65 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
66 int res = connect(sockfd,(struct sockaddr*)&addr,
67 sizeof(addr));
68 if (res == -1){
69 perror("connect"),exit(-1);
70 }
71 printf("连接成功\n");
72 printf(",发送消息时注意:[%%]与[$$]用作服务端判断订阅与取消订阅类型的消息头\n");
73 read_run();
74 while(1)
75 {
76 char buffer[100];
77 char input;
78 char ch;
79 printf("输入\n[1]:发送消息\n[2]:增加订阅消息到服务器\n[3]:取消服务器已订阅消息\n[4]:增加本地订阅消息\n[5]:取消本地已订阅消息\n[6]:退出\n");
80 scanf("%c",&input);
81 while ((ch = getchar()) != '\n')
82 {
83 ;
84 }
85 switch (input)
86 {
87 case '1':
88 {
89 printf("发送消息类型(与订阅消息相关,一个字符),按下enter输入\n");
90 scanf("%c",&input);
91 while ((ch = getchar()) != '\n')
92 {
93 ;
94 }
95 printf("输入发送消息,按下enter键发送\n");
96 memcpy(buffer,&input,1);
97 scanf("%s",buffer+1);
98 while ((ch = getchar()) != '\n')
99 {
100 ;
101 }
102 write(sockfd,(void *)&buffer,100);
103 }
104
105 break;
106 case '2':
107 {
108 {
109 printf("输入订阅消息(一个字符),按下enter键发送\n");
110 scanf("%c",&input);
111 while ((ch = getchar()) != '\n')
112 {
113 ;
114 }
115 memcpy(buffer,"%%",2);
116 memcpy(buffer+2,&input,1);
117 write(sockfd,(void *)&buffer,100);
118 }
119 }
120 break;
121 case '3':
122 {
123 {
124 printf("输入取消订阅消息(一个字符),按下enter键发送\n");
125 scanf("%c",&input);
126 while ((ch = getchar()) != '\n')
127 {
128 ;
129 }
130 memcpy(buffer,"$$",2);
131 memcpy(buffer+2,&input,1);
132 write(sockfd,(void *)&buffer,100);
133 }
134 }
135
136 break;
137 case '6':
138 {
139 printf("exiting...\n");
140 exit_thread=true;
141 close(sockfd);
142 printf("exit success\n");
143 return 0;
144 }
145 break;
146 case '4':
147 {
148 {
149 printf("输入订阅消息(一个字符),按下enter键增加订阅\n");
150 scanf("%c",&input);
151 while ((ch = getchar()) != '\n')
152 {
153 ;
154 }
155 bool pushsub=true;
156 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
157 {
158 if(*it==input)
159 {
160 pushsub=false;
161 }
162 }
163 if(pushsub==true)
164 subscribes.push_back(((int)input));
165 printf("all subscribes msg:\n");
166 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
167 {
168 printf("[%c] ",*it);
169 }
170 printf("\n");
171 }
172 }
173 break;
174 case '5':
175 {
176 printf("输入取消订阅消息(一个字符),按下enter键取消订阅\n");
177 scanf("%c",&input);
178 while ((ch = getchar()) != '\n')
179 {
180 ;
181 }
182 printf("client cancel subscribe msg is:");
183 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
184 {
185 if(*it==input)
186 {
187 printf("[%c]\n",*it);
188 subscribes.erase(it);
189 break;
190 }
191 }
192 printf("all subscribes msg:");
193 for(vector<int>::iterator it=subscribes.begin();it!=subscribes.end();it++)
194 {
195 printf("[%c] ",*it);
196 }
197 printf("\n");
198 }
199
200 break;
201
202 default:
203 break;
204 }
205 }
206 return 0;
207 }