首页 > 学院 > 开发设计 > 正文

liunx 多进程不阻塞I/O

2019-11-08 18:25:37
字体:
来源:转载
供稿:网友

思路

  多进程的特性是复制父进程的所有数据,这和多线程的公用内存不一样,多进程的好处在于不容易出现一些麻烦的内存问题,多线程的互斥是一件很麻烦的事情,当然也因为这样,多进程也拥有自己的局限性。

  利用 多进程+阻塞I/O 的方式实现不阻塞I/O,简单来说就是每accept到一个新的连接,就创建一个子进程,通过那个子进程来单方面通信,子进程里面还是用的最简单的阻塞I/O,这样的话就能实现维护多用户同时连接的问题,当然这样还是不能实现异步I/O,想要实现异步I/O的话,可以在子进程里面创建一个子线程,主线程加子线程就可以实现异步I/O,我这里只是一个简单的实现,前后不过花了我十几分钟时间,所以没加多线程的内容。

  子进程复制了父进程的数据,所以可以利用父进程里面的套接字和sockaddr。

代码实现

我这里是用的标准C写的,没有C/C++混写,写得比较丑,因为只是一个简单的demo,所以没有考虑代码风格的问题

/********************************************************* * Author			: crazy_mad * Last modified	: 2017-01-16 15:39 * Filename			: main.c * Description		:  *********************************************************/#include <sys/socket.h>#include <sys/types.h>#include <arpa/inet.h>#include <netinet/in.h>#include <errno.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <sys/wait.h>#include <unistd.h>#define BUF_LENGTH 256  	// buf长度int main(int argc, char* argv[]){		int on = 1;	int server_fd = socket(AF_INET, SOCK_STREAM, 0);	// 设置socket模式,这里主要是设置的tcp和重复使用地址	if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {		PRintf("setsockopt error: %s/n", strerror(errno));		exit(1);	}	socklen_t len = sizeof(struct sockaddr_in);	struct sockaddr_in server_addr, client_addr;		// 客户端、服务端地址信息	server_addr.sin_family = AF_INET;						server_addr.sin_port = htons(8001);	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);	// 绑定地址	if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {		printf("bind error: %s/n", strerror(errno));		exit(1);	}	memset(&client_addr, 0, sizeof(client_addr));	listen(server_fd, 10);	while (1) {		int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);		char buf[BUF_LENGTH] = { 0 };		// 创建子进程		pid_t child = fork();		int status;		if (child == -1) {	 		// 创建子进程失败			perror("fork");			exit(EXIT_FAILURE);		} else if (child == 0) {	// 创建子进程成功			printf("child pid=%d ppid=%d created/n", getpid(), getppid());			int ret;			while (1) {				ret = recv(client_fd, buf, BUF_LENGTH, 0);				if (ret <= 0) {		// socket连接断开(或其他异常)					break;				}				printf("%s/n", buf);			};			printf("child pid=%d exit!/n", getpid());			close(client_fd);		// 回收客户端套接字			exit(EXIT_SUCCESS);		} else {					// 子进程成功退出			//printf("parent pid=%d ppid=%d/n", getpid(), getppid());			int w = waitpid(child, &status, WUNTRACED | WCONTINUED);			if (w == -1) {			// 子进程退出异常				perror("waitpid");				exit(EXIT_FAILURE);			} else {				// 子进程正常退出				//printf("child exited/n");			}		}	}	close(server_fd);				// 回收套接字	return 0;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表