TCP/IP网络编程 学习笔记_12 --进程间通信
2015-08-19 14:45
591 查看
进程间通信的基本概念
进程间通信意味着两个不同进程间可以交换数据,但从上一章节我们知道,不同进程间内存是相互独立的,那么要实现不同进程间通信,就得有一个它们都能访问的公共区域内存做媒介,这个媒介不属于进程,而是和套接字一样,属于操作系统。所以,两个进程通过操作系统提供的内存空间进行通信,我们把这块内存空间称作管道。创建管道函数
int pipe(int filedes[2]);
成功时返回0,失败时返回-1
参数:
filedes[0]:通过管道接收数据时使用的文件描述符,即管道出口
filedes[1]:通过管道传输数据时使用的文件描述符,即管道入口
示例如下:
#define BUF_SIZE 30 int main(int argc, char *argv[]) { int fds[2];//保存I/O的文件描述符 char str[] = "Who are you?"; char buf[BUF_SIZE]; pid_t pid; pipe(fds);//创建管道 pid = fork();//子进程也复制了I/O的文件描述符 if(pid == 0) { write(fds[1], str, sizeof(str)); } else { read(fds[0], buf, BUF_SIZE); puts(buf); } return 0; }
上面这个示例数据只是单向传递的,想想如果要进行双向传递这么写可以吗?因为当前管道的数据如果被两个进程都要读,那么先读的进程会先取走管道中的数据,这样另一个进程就会阻塞一直等待下去。所以,要实现进程间双向通信,用一个管道是很难实现的,我们下面来讨论一种简单的实现方式–创建两个管道。
双向通信示例:
#define BUF_SIZE 30 int main(int argc, char *argv[]) { int fds1[2], fds2[2]; char str1[] = "Who are you?"; char str2[] = "Thank you for your message"; char buf[BUF_SIZE]; pid_t pid; pipe(fds1), pipe(fds2); pid = fork(); if(pid == 0) { write(fds1[1], str1, sizeof(str1));//发送到管道1 read(fds2[0], buf, BUF_SIZE);//从管道2中读 printf("Child proc output: %s \n", buf); } else { read(fds1[0], buf, BUF_SIZE);//从管道1中读 printf("Parent proc output: %s \n", buf); write(fds2[1], str2, sizeof(str2));//发送到管道2 sleep(3); } return 0; }
运用进程间通信
这里我们扩展上一章节写的回声程序,将客服端传输到服务端的字符串保存到本地文件中。我们可以将这个任务委托给另外的进程,即在服务端再开一个进程来做这个任务,这里就涉及了进程间数据交换的问题。// // main.cpp // hello_server // // Created by app05 on 15-8-19. // Copyright (c) 2015年 app05. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <arpa/inet.h> #include <sys/socket.h> #include <signal.h> #define BUF_SIZE 100 void error_handling(char *message); void read_childproc(int sig); int main(int argc, const char * argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr; int fds[2]; pid_t pid; struct sigaction act; socklen_t adr_sz; int str_len, state; char buf[BUF_SIZE]; if (argc != 2) { printf("Usage: %s <port> \n", argv[0]); exit(1); } act.sa_handler = read_childproc; sigemptyset(&act.sa_mask); act.sa_flags = 0; state = sigaction(SIGCHLD, &act, 0); serv_sock = socket(PF_INET, SOCK_STREAM, 0); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr *) &serv_adr, sizeof(serv_adr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 5) == -1) error_handling("listen() error"); /*创建子进程来执行文件写入*/ pipe(fds); //创建交换数据管道 pid =fork(); if (pid == 0) { FILE *fp = fopen("/Users/app05/Desktop/server-clint/hello_server/hello_server/echonmsg.txt", "wb"); char msgbuf[BUF_SIZE]; int i, len; for (i = 0; i < 10; i++) { len = read(fds[0], msgbuf, BUF_SIZE); fwrite((void *)msgbuf, 1, len, fp); } fclose(fp); return 0; } while (1) { adr_sz = sizeof(clnt_adr); clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &adr_sz); if(clnt_sock == -1) continue; else puts("new client connected..."); pid = fork(); if(pid == -1) { close(clnt_sock); continue; } if (pid == 0) { close(serv_sock); while((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0) { write(clnt_sock, buf, str_len); write(fds[1], buf, str_len); //将客服端发送来的数据发往管道 } close(clnt_sock); puts("client disconnected..."); return 0; } else close(clnt_sock); } close(serv_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } void read_childproc(int sig) { pid_t pid; int status; pid = waitpid(-1, &status, WNOHANG); printf("removed proc id: %d \n", pid); }
注释:像这种多进程服务器开销很大,实际中我们一般不会这么用,本节和上一节内容主要目的是学习多进程的理论知识。
这里的套接字关闭也存在问题,下次启动就永久性的bind()失败,再者,管道中的数据也读取不到文件中,具体原因待查……………………………..(初步估计是这个多进程操作引起的…)
相关文章推荐
- TCP/IP网络编程 学习笔记_12 --进程间通信
- 安卓imageview获取网络图片
- linux查看网络状态
- 网络数据分析器
- httpd.conf 禁止运行PHP和html页面
- Linux网络编程下send到一个disconnected socket上
- springmvc使用和经验总结(长沙师说网络科技有限公司)
- 网络系统设计过程
- Android 判断用户2G/3G/4G移动数据网络
- ftp,http,https有啥区别?
- httpd源码分析
- ZOJ 3814 Sawtooth Puzzle (2014年牡丹江赛区网络赛F题)
- HTTP 错误 404.2 - Not Found
- HTTP 错误 404.17 - Not Found
- TCP/IP,http,socket,长连接,短连接
- linux socket网络编
- iOS网络-02-数据解析(JSON与XML)
- HttpClient post 请求实例
- Python入门网络爬虫之精华版
- 【转】 VC中TCP实现 异步套接字编程的原理+代码