标签:
在网络课程中,有讲到Socket编程,对于tcp讲解的环节,为了加深理解,自己写了Linux下进程Socket通信,在学习的过程中,又接触到了其它的几种方式。记录一下。
管道通信,在一个进程之中,只能单一的对其写或者是读,而不可以及执行写操作又执行读操作。这一点,我们可以将其想象成我们的水管,分别连着不同的两端,在有水流的时候,一端只能进行输入,另一端只能进行输出,而不可以同时输入和输出。
管道又分为有名管道和匿名管道,两者的区别在于对于匿名管道,其只能在具有亲缘关系的父子进程之间进行消息通信。管道的通信是借助于在我们的磁盘上生成一个文件,然后对文件的读写来实现我们的通信,而且数据被读之后,在文件中将会被删除掉。
匿名管道的实现较为简单,实现代码:
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <memory.h> 5 #include <errno.h> 6 7 #define BUFFER_SIZE 9 8 9 10 int main(int argc, char const *argv[]) 11 { 12 int n; 13 int fd[2]; 14 pid_t pid; 15 char sendBuffer[BUFFER_SIZE]="welcome!"; 16 char receiveBuff[BUFFER_SIZE]; 17 memset(receiveBuff,0,sizeof(receiveBuff)); 18 19 if (pipe(fd)==-1) 20 { 21 fprintf(stderr, "pipe:%s\n",strerror(errno)); 22 exit(1); 23 } 24 25 if ((pid=fork())<0) 26 { 27 fprintf(stderr, "fork:%s\n",strerror(errno)); 28 exit(1); 29 }else if (pid>0)//parent process 30 { 31 close(fd[0]);//close the read part 32 write(fd[1],sendBuffer,BUFFER_SIZE); 33 printf("parent process send:%s\n", sendBuffer); 34 }else 35 { 36 close(fd[1]);//close the write part 37 read(fd[0],receiveBuff,BUFFER_SIZE); 38 printf("child process receive:%s\n",receiveBuff); 39 } 40 return 0; 41 } 42 43 /* 44 [Test] 45 gcc -o pipe pipe.c 46 ./pipe 47 parent process send:welcome! 48 child process receive:welcome 49 */
1.创建管道2.通过fork函数分叉出子进程3.写数据4.读数据5.关闭管道读端和写端。这里也除了管道函数,还要特别说一下的是fork函数。
fork函数返回的数据在父进程中是子进程pid,而对子进程返回的是0,这并不是说,子进程的pid就是零,还有一个函数是getpid(),执行这个函数后,在子进程和父进程中得到的都是该进程pid,而不是fork函数的返回值。fork函数执行的时候,是将父进程中全部的数据置入自己进程之中,和父进程中的数据不是同步的了。
通过pipe函数我们创建了一个管道,管道接收的参数是一个长度为2的一维数组,此时,此时在0位返回的是读端口,1位返回的是写端口,当我们要对数据进行写入的时候,我们需要关闭其读端口,如果对其进行读操作,我们要关闭写端口。类似于读文件的操作,制定数据和大小,然后通过read和write函数对其进行读写。
通过对于匿名管道的分析,再到有名管道,为什么有名管道可以被非亲缘进程找到利用?因为它有名呀,对的,如果在家中,父亲要和儿子谈话,只需说出来就好了,因为信道上的接听者只有父亲和儿子,所以即使不指儿子的名字和儿子说,儿子也是知道是在和他讲,但是如果要和别人讲话,而且由很多人同时在侦听信道的时候,如果我们不指定名字,他们就不会知道我们是在跟谁讲话。所以对于有名管道,我们首先要对其指定一个名字,然后指定作为写端或者是读端,然后对其进行操作。
1 #include <unistd.h> 2 #include <fcntl.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <limits.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <errno.h> 9 10 #define FIFO_NAME "/home/louxj/workspace/networking/ipc/myfifo" 11 #define PIPE_BUFF 12 12 13 int main(int argc, char const *argv[]) 14 { 15 int res=0; 16 int pipe_id; 17 char buffer[PIPE_BUFF]="hello,fifo"; 18 19 if (access(FIFO_NAME,F_OK)==0)//test wether the file exits 20 { 21 if ((res=mkfifo(FIFO_NAME,0777)))!=0) 22 { 23 fprintf(stderr, "mkfifo:%s\n", strerror(errno)); 24 } 25 if ((pipe_id=open(FIFO_NAME,O_RDWR))!=-1) 26 { 27 if (write(pipe_id,buffer,sizeof(buffer))) 28 { 29 printf("write success\n"); 30 close(pipe_id); 31 }else 32 { 33 fprintf(stderr, "write:%s\n",strerror(errno)); 34 exit(1); 35 } 36 }else 37 { 38 fprintf(stderr, "open:%s\n",strerror(errno)); 39 } 40 } 41 return 0; 42 }
因为管道是通过本地磁盘上的文件进行信息的交换,因此我们需要给予其本地磁盘上的一个文件目录,然后根据该目录通过access()函数来获取该管道,如果获取失败,那么我们就按照给定的目录创建一个,创建管道的时候,我们需要制定是对其进行读还是写,创建好之后,通过指定模式打开我们的管道,此时会得到一个管道号,然后根据获得管道标志号,作为参数,进行read和write操作。下面是读端的执行代码。
1 #include <unistd.h> 2 #include <fcntl.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <limits.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <errno.h> 9 10 #define FIFO_NAME "/home/louxj/workspace/networking/ipc/myfifo" 11 #define PIPE_BUFF 12 12 13 int main(int argc, char const *argv[]) 14 { 15 char buffer[PIPE_BUFF]; 16 int pipe_id; 17 int size = sizeof(buffer); 18 19 if ((pipe_id=open(FIFO_NAME,O_RDWR))!=-1) 20 { 21 read(pipe_id,(void *)buffer,size); 22 printf("%s\n",(char *)buffer); 23 }else 24 { 25 fprintf(stderr, "open:%s\n", strerror(errno)); 26 exit(1); 27 } 28 return 0; 29 }
Socket通信,不仅仅是一台主机上的两个进程可以进行通信,还可以让处在因特网中的两个进程进行通信。在两个进程进行通信的时候,首先本地的进程在运行的时候会绑定一个端口,然后我们本地为该进程生成一个缓冲区,返回一个值,即为socket作为对其进行标记,每当本地进程和远程一个进程建立连接的时候,就会根据远程进程的信息和本地进程的信息生成一个socket,然后双方借助于socket就可以进行通信,运输层得到的数据写入socket标志的缓冲区,然后在里面进行相应的操作之后将其提交给网络层。相比其它的几种处理方式,该中方式比较麻烦。多于服务端,通过listen阻塞监听,监听到有连接请求,通过accept函数得到一个本地与之对应的缓冲区,然后创建一个进程用来和该连接进行交互,然后通过receive来接收信息,由于c语言大一学过去之后,基本没怎么再看过,所以写来的时候还是遇到了几个小坑。这里实现的是当连接建立后,服务端给本地端发送一个连接建立提示,然后客户端可以向服务端发送消息,服务端给予一个I don‘t know的回复。
服务端代码
1 ///////////////////////////////////////// 2 // the server code for TCP socket // 3 ///////////////////////////////////////// 4 5 #include <netinet/in.h> //for sockaddr_in 6 #include <sys/types.h> //for socket 7 #include <sys/socket.h> //for socket 8 #include <stdio.h> //for printf 9 #include <stdlib.h> //for exit 10 #include <string.h> //for memset 11 #include <time.h> //for time_t and time 12 #include <fcntl.h> 13 #include <errno.h> //for errno 14 15 #define SERVER_PORT 5790 16 #define LENGTH_OF_QUEUE 20 17 #define BUFFER_SIZE 1024 18 19 int main(int argc, char const *argv[]) 20 { 21 struct sockaddr_in server_addr;//define a universal socket struct 22 23 bzero(&server_addr,sizeof(server_addr));//clear the memory to zero 24 server_addr.sin_family=AF_INET;//IPv4 protocol 25 server_addr.sin_addr.s_addr=htons(INADDR_ANY);//set the IP address with localhost IP address 26 server_addr.sin_port=htons(SERVER_PORT);//set the nameed port 27 28 //time_t now; 29 30 31 //create the socket for the server 32 int server_socket; 33 if ((server_socket=socket(AF_INET,SOCK_STREAM,0))==-1) 34 { 35 fprintf(stderr, "socket:%s\n", strerror(errno)); 36 exit(1); 37 } 38 39 //bind the socket with the socket address 40 if ((bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))==-1) 41 { 42 fprintf(stderr, "bind:%s\n", strerror(errno)); 43 exit(1); 44 } 45 46 //set the server‘s socket to listen for the request from the clients 47 if ((listen(server_socket,LENGTH_OF_QUEUE))==-1) 48 { 49 fprintf(stderr, "listen:%s\n", strerror(errno)); 50 exit(1); 51 } 52 53 //set the server running all the time 54 while(1) 55 { 56 struct sockaddr_in client_addr;//define a socket struct for each client 57 socklen_t length=sizeof(client_addr); 58 int new_server_socket; 59 if ((new_server_socket=accept(server_socket,(struct sockaddr*)&client_addr,&length))<0) 60 { 61 fprintf(stderr, "accept:%s\n", strerror(errno)); 62 break; 63 } 64 65 //set the notice info to send to the client 66 char buffer[BUFFER_SIZE]; 67 bzero(buffer,BUFFER_SIZE); 68 strcpy(buffer,"Hello,coming from the server!"); 69 strcat(buffer,"\n"); 70 71 send(new_server_socket,buffer,BUFFER_SIZE,0); 72 73 bzero(buffer,BUFFER_SIZE); 74 75 //receive the data to send to the client 76 length=recv(new_server_socket,buffer,BUFFER_SIZE,0); 77 if (length<0) 78 { 79 fprintf(stderr, "recv:%s\n", strerror(errno)); 80 exit(1); 81 } 82 //display the data receive from the client 83 printf("%s\n",buffer); 84 85 //send the local file stream to the client 86 int stream; 87 if ((stream=open("send_data",O_RDWR))==-1) 88 { 89 fprintf(stderr, "open:%s\n", strerror(errno)); 90 exit(1); 91 }else 92 { 93 printf("The file send_data was opened.\n"); 94 } 95 96 97 int lengthsize=0; 98 int i=0; 99 while((lengthsize=read(stream,buffer,sizeof(buffer)))>0) 100 { 101 printf("lengthsize=%d\n",lengthsize); 102 //printf("%s\n", buffer); 103 if (send(new_server_socket,buffer,lengthsize,0)<0) 104 { 105 printf("send file failed!\n"); 106 break; 107 } 108 else 109 { 110 printf("the %d time to send...\n",++i); 111 } 112 bzero(buffer,BUFFER_SIZE); 113 } 114 if (close(stream)==-1) 115 { 116 fprintf(stderr, "close%s\n", strerror(errno)); 117 exit(1); 118 } 119 close(new_server_socket);//close the connection with the client 120 } 121 122 //close the socket for listening 123 close(server_socket); 124 return 0; 125 } 126 127 /* 128 [Test] 129 gcc -o tcp_server tcp_server.c 130 ./tcp_server 131 Hello,this is client A! 132 The file send_data was opened. 133 lengthsize=1024 134 the 1 time to send... 135 lengthsize=1024 136 the 2 time to send... 137 lengthsize=1024 138 the 3 time to send... 139 lengthsize=1024 140 the 4 time to send... 141 lengthsize=1024 142 the 5 time to send... 143 lengthsize=805 144 the 6 time to send... 145 */
其中涉及到创建进程与结束进程等还是比较复杂的。下面通过一个流程图说明其工作原理
对于其中的一些函数,有自己的英文注释,想锻炼下英文表达能力,但是表达在语法和意思上还是有些错误的。
客户端工作代码
1 ///////////////////////////////////////// 2 // the client code for TCP socket // 3 ///////////////////////////////////////// 4 5 #include <netinet/in.h> //for sockaddr_in 6 #include <sys/types.h> //for socket type 7 #include <sys/socket.h> //for socket() 8 #include <stdio.h> //for printf 9 #include <stdlib.h> //for exit 10 #include <string.h> //for memset 11 #include <time.h> //for time_t and time 12 #include <arpa/inet.h> //for INTERNET definition 13 #include <fcntl.h> 14 #include <errno.h> //for errno 15 16 #define SERVER_PORT 5790 17 #define BUFFER_SIZE 1024 18 19 int main(int argc, char const *argv[]) 20 { 21 if (argc!=2) 22 { 23 printf("Usage:%s ServerIPAddress\n",argv[0]); 24 exit(1); 25 } 26 27 28 struct sockaddr_in client_addr;//define a universal socket struct 29 bzero(&client_addr,sizeof(client_addr));//clear the memory to zero 30 client_addr.sin_family=AF_INET;//internet protocol family 31 client_addr.sin_addr.s_addr=htons(INADDR_ANY);//INADDR_ANY represents the localhost ip address 32 client_addr.sin_port=htons(0);//0 represents the system will automatically allocate a free port 33 34 int client_socket; 35 if ((client_socket=socket(AF_INET,SOCK_STREAM,0))<0) 36 { 37 fprintf(stderr, "socket:%s\n", strerror(errno)); 38 exit(1); 39 } 40 41 if (bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr))<0) 42 { 43 fprintf(stderr, "bind:%s\n", strerror(errno)); 44 exit(1); 45 } 46 47 struct sockaddr_in server_addr; 48 bzero(&server_addr,sizeof(server_addr)); 49 server_addr.sin_family=AF_INET;//IPv4 protocol 50 if (inet_aton(argv[1],&server_addr.sin_addr)==0)//convert the input ip address 51 { 52 fprintf(stderr, "server address:%s\n", strerror(errno)); 53 exit(1); 54 } 55 server_addr.sin_port=htons(SERVER_PORT); 56 57 58 socklen_t server_addr_lentth=sizeof(server_addr); 59 if (connect(client_socket,(struct sockaddr*)&server_addr,server_addr_lentth)<0) 60 { 61 fprintf(stderr, "can‘t connect to:%s because that %s:\n", argv[1],strerror(errno)); 62 exit(1); 63 } 64 65 char buffer[BUFFER_SIZE]; 66 bzero(buffer,BUFFER_SIZE); 67 68 int length; 69 if ((length=recv(client_socket,buffer,BUFFER_SIZE,0))<0) 70 { 71 fprintf(stderr, "recv:%s\n", strerror(errno)); 72 exit(1); 73 } 74 printf("\n%s\n",buffer); 75 76 bzero(buffer,BUFFER_SIZE); 77 78 strcpy(buffer,"Hello,this is client A!\n"); 79 send(client_socket,buffer,BUFFER_SIZE,0); 80 81 int stream; 82 if ((stream=open("receive_data",O_RDWR))==-1) 83 { 84 printf("The file data was not opened!\n"); 85 }else 86 bzero(buffer,BUFFER_SIZE); 87 88 length=0; 89 while(length=recv(client_socket,buffer,BUFFER_SIZE,0)) 90 { 91 if (length<0) 92 { 93 printf("Receive data from server %s failed!\n", argv[1]); 94 break; 95 } 96 97 int write_lenth=write(stream,buffer,sizeof(buffer)); 98 if (write_lenth<length) 99 { 100 printf("File write Failed!\n"); 101 break; 102 } 103 bzero(buffer,BUFFER_SIZE); 104 } 105 printf("Receive File From Server [%s] Finished.\n",argv[1]); 106 107 //close the file 108 close(stream); 109 110 //close the socket 111 close(client_socket); 112 return 0; 113 } 114 115 /* 116 [Test] 117 gcc -o tcp_client tcp_client.c 118 ./tcp_client 127.0.0.1 119 Hello,coming from the server! 120 Receive File From Server [127.0.0.1] Finished. 121 */
共享内存的通信方式,系统根据我的偏好设置在内存中开辟一块空间,并对其进行相应的指定,然后我们的另一个进程可以按照同样的指定,也就是其标记,对其进行访问。创建共享内存,得到共享内存后,想内存中写入数据,然后另个进程得到内存,然后从中读出数据。
写入方代码实现:
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <sys/shm.h> 5 #include <sys/ipc.h> 6 #include <string.h> 7 #include <errno.h> 8 9 #define PATH "/tmp" 10 #define SIZE 1024 11 #define ID 0 12 13 int main(int argc, char const *argv[]) 14 { 15 void *shmAddr=NULL; 16 char dataAddr[]="Hello"; 17 key_t key=ftok(PATH,ID);//create an unique key for the current IPC 18 19 //create a shared memory area in the current process memory 20 int shmid; 21 if ((shmid=shmget(key,SIZE,0666|IPC_CREAT))==-1) 22 { 23 fprintf(stderr, "shmget:%s\n", strerror(errno)); 24 exit(1); 25 } 26 27 28 29 shmAddr=shmat(shmid,(void*)0,0);//map the shared memory to the process memory 30 if(shmAddr==(void*)-1) 31 { 32 fprintf(stderr, "shmat:%s\n", strerror(errno)); 33 } 34 strcpy(shmAddr,dataAddr);//copy the dataAddr to shmAddr 35 36 37 38 39 //disconnect the process memory with the shared memory 40 if (shmdt(shmAddr)==-1) 41 { 42 fprintf(stderr, "shmdt:%s\n", strerror(errno)); 43 } 44 return 0; 45 } 46 47 /* 48 [Test] 49 gcc -o shm_write shm_write.c 50 ./shm_write 51 */
读取方代码实现:
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <sys/shm.h> 5 #include <sys/ipc.h> 6 #include <string.h> 7 #include <errno.h> 8 9 #define PATH "/tmp" 10 #define SIZE 1024 11 #define ID 0 12 13 int main(int argc, char const *argv[]) 14 { 15 char * shmAddr; 16 char * dataAddr="world"; 17 key_t key=ftok(PATH,ID); 18 19 //create a shared memory area int the current pprocess memory 20 int shmid; 21 if ((shmid=shmget((key_t)key,SIZE,0666|IPC_CREAT))==-1) 22 { 23 fprintf(stderr, "shmget:%s\n", strerror(errno)); 24 exit(1); 25 } 26 27 28 shmAddr=shmat(shmid,(void*)0,0);//map the shared memory to the process memory 29 if(shmAddr==(void*)-1) 30 { 31 fprintf(stderr, "shmat:%s\n", strerror(errno)); 32 } 33 34 printf("%s\n",shmAddr); 35 36 37 shmdt(shmAddr); 38 shmctl(shmid,IPC_RMID,NULL); 39 40 return 0; 41 } 42 43 /* 44 [Test] 45 gcc -o shm_read shm_read.c 46 ./shm_read 47 Hello 48 */
消息队列和有名管道有些类似的地方,最大相同点在于它可以用于在不同的进程之间进行通信,但是管道有一个劣势是,对于接收端其对与管道内的数据只能是接受,而不可以对其进行过滤选择,同时在写和读的时候还会出现堵塞.对于消息队列其在接收的时候也是会发生堵塞的,解除阻塞,只有当其接收到合适的消息或者该队列被删除了,这个阻塞才会解除。对于消息队列的通信流程是创建消息-》获得队列--》向队列中发送消息--》从队列中取出消息。
接收端实现代码:
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <errno.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <sys/ipc.h> 9 #include <sys/msg.h> 10 11 #define MSG_FILE "/tmp" //a pathname for generating a unique key 12 #define BUFFER 512 //set the buffer size to 255 bytes 13 #define PERM S_IRUSR|S_IWUSR //allow the user to read and write 14 15 struct msgbuffer 16 { 17 long mtype; 18 char mtext[BUFFER+1]; 19 }; 20 typedef struct msgbuffer msgbuf; 21 22 int main(int argc, char const *argv[]) 23 { 24 //create a unique key 25 key_t key; 26 if ((key=ftok(MSG_FILE,BUFFER))==-1) 27 { 28 fprintf(stderr, "ftok:%s\n", strerror(errno)); 29 exit(1); 30 }else 31 { 32 printf("generate a key=%d\n", key); 33 } 34 35 //get a message queue 36 int msgid; 37 msgbuf msg; 38 if ((msgid=msgget(key,PERM|IPC_CREAT))==-1) 39 { 40 fprintf(stderr, "msgget:%s\n", strerror(errno)); 41 exit(1); 42 } 43 44 //get a message from the queue everytime 45 int i; 46 for (i = 0; i < 3; ++i) 47 { 48 msgrcv(msgid,&msg,sizeof(msgbuf),1,0); 49 printf("Receiver receive: %s\n", msg.mtext); 50 } 51 52 //send the message to notice the sender 53 msg.mtype=2; 54 char * myask="3 messages have received from you"; 55 strncpy(msg.mtext,myask,BUFFER); 56 msgsnd(msgid,&msg,sizeof(msgbuf),IPC_NOWAIT); 57 58 return 1; 59 } 60 61 62 /* 63 [Test] 64 gcc -o msg_receiver msg_receiver.c 65 ./msg_reveiver 66 generate a key=589827 67 Receiver receive: I‘m sender,there are some messages for you. 68 Receiver receive: Message 1 69 Receiver receive: Message 2 70 */
发送端实现代码:
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <errno.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <sys/ipc.h> 9 #include <sys/msg.h> //for msg_get(),msg_rcv() 10 11 #define MSG_FILE "/tmp" //a pathname for generating a unique key 12 #define BUFFER 512 //set the buffer size to 255 bytes 13 #define PERM S_IRUSR|S_IWUSR //allow the user to read and write 14 15 struct msgbuffer 16 { 17 long mtype; 18 char mtext[BUFFER+1]; 19 }; 20 typedef struct msgbuffer msgbuf; 21 22 //create three message 23 char* message[3]={"I‘m sender,there are some messages for you.","Message 1","Message 2"}; 24 25 int main(int argc, char const *argv[]) 26 { 27 msgbuf msg; 28 key_t key; 29 int msgid; 30 31 //create a unique key 32 if ((key=ftok(MSG_FILE,BUFFER))==-1) 33 { 34 fprintf(stderr, "ftok:%s\n", strerror(errno)); 35 exit(1); 36 }else 37 { 38 printf("generate a key=%d\n", key); 39 } 40 41 //get a message queue 42 if ((msgid=msgget(key,PERM|IPC_CREAT))==-1) 43 { 44 fprintf(stderr, "msgget:%s\n", strerror(errno)); 45 exit(1); 46 } 47 48 //set the type of the message 49 msg.mtype=1; 50 51 //send three messages to the receiver 52 int i; 53 for (i = 0; i <3; ++i) 54 { 55 strncpy(msg.mtext,message[i],BUFFER); 56 msgsnd(msgid,&msg,sizeof(msgbuf),IPC_NOWAIT); 57 } 58 59 //receive the response from the receiver 60 memset(&msg,‘\0‘,sizeof(msgbuf));//clear the msgbuf 61 /*receive the message,the third arguments show the type of message will be received */ 62 msgrcv(msgid,&msg,sizeof(msgbuf),2,0); 63 printf("This is a message from the receiver,%s\n", msg.mtext); 64 65 66 //delete the message queue. 67 if (msgctl(msgid,IPC_RMID,0)==-1) 68 { 69 fprintf(stderr, "ftok:%s\n", strerror(errno)); 70 exit(1); 71 } 72 return 1; 73 } 74 75 /* 76 [Test] 77 gcc -o msg_sender msg_sender.c 78 ./msg_sender 79 generate a key=589827 80 This is a message from the receiver,3 messages have received from you 81 */
对于消息通信,其中的几个函数,这里在说明一下,msgrcv和msgsnd两个函数,对于其中的参数,第一个指定的是我们的消息队列的标示符,然后第二个是消息区域,然后是我们的消息长度,然后是消息类型,最后一个是用来指定是否堵塞。
上述为Linux下进程间通信的四种方式,实际开发中,我们传输数据类型和进程间的关系选择合适的方式。
【网络编程基础】Linux下进程通信方式(共享内存,管道,消息队列,Socket)
标签:
原文地址:http://www.cnblogs.com/lou424/p/5018966.html