多進程併發編程----基於高級的動態創建進程池的模型

此篇博文主要講解如何動態創建進程的方法,此方法模型如下:

<span style="font-size:18px;">main{
  ps=socket();
  bind();
  listen();
  while(1){
    cs=accept();
    if(cs){
    	pid=fork();
    	if(pid==0){//子進程處理
    		close(ps);
    		do_child(cs);
    	}
    	else{//父進程處理
    		.......
    		close(cs);
    	}
    }
  }
}
do_child(cs){
  read();
  write();
  close(cs);
}</span>
下面用代碼介紹如何使用此種模型:

服務端程序:

<span style="font-size:18px;">#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFLEN 1024
#define SERVER_PORT 8888
#define BACKLOG 5

static void handle_request(int s_c)
{
	printf("process %d is being to handle client %d\n",getpid(),s_c);
	
	time_t now;		/*時間*/
	char buff[BUFFLEN];/*收發數據緩衝區*/
	int n = 0;
	memset(buff, 0, BUFFLEN);/*清零*/
	n = recv(s_c, buff, BUFFLEN,0);/*接收發送方數據*/
	if(n > 0 && !strncmp(buff, "TIME", 4))/*判斷是否合法接收數據*/
	{
		memset(buff, 0, BUFFLEN);/*清零*/
		now = time(NULL);/*當前時間*/
		sprintf(buff, "%24s\r\n",ctime(&now));/*將時間拷貝入緩衝區*/
		send(s_c, buff, strlen(buff),0);/*發送數據*/
	}		
	/*關閉客戶端*/
	close(s_c);	
}

static void handle_connect(int s_s)
{
	
	int s_c;	/*客戶端套接字文件描述符*/
	struct sockaddr_in from;	/*客戶端地址*/
	int len = sizeof(from);
	
	/*主處理過程*/
	while(1)
	{
		/*接收客戶端連接*/
		s_c = accept(s_s, (struct sockaddr*)&from, &len);
		if(s_c > 0)/*客戶端成功連接*/
		{
			/*創建進程進行數據處理*/
			if(fork() > 0){/*父進程*/
				close(s_c);/*關閉父進程的客戶端連接套接字*/
			}else{
				handle_request(s_c);/*處理連接請求*/
				exit(0);	
			}
		}
	}
		
}


int main(int argc, char *argv[])
{
	int s_s;	/*服務器套接字文件描述符*/
	struct sockaddr_in local;	/*本地地址*/	
	
	/*建立TCP套接字*/
	s_s = socket(AF_INET, SOCK_STREAM, 0);
	
	int optval=1;
	int ret=setsockopt(s_s,SOL_SOCKET,SO_REUSEADDR,(int *)&optval,sizeof(optval));
	
	/*初始化地址接哦股*/
	memset(&local, 0, sizeof(local));/*清零*/
	local.sin_family = AF_INET;/*AF_INET協議族*/
	local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
	local.sin_port = htons(SERVER_PORT);/*服務器端口*/
	
	/*將套接字文件描述符綁定到本地地址和端口*/
	int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
	err = listen(s_s, BACKLOG);/*偵聽*/
	
	/*處理客戶端連接*/
	handle_connect(s_s);
	
	close(s_s);
	
	return 0;		
}
</span>

客戶端程序:

<span style="font-size:18px;">#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

#define BUFFLEN 1024
#define SERVER_PORT 8888
int main(int argc, char *argv[])
{
	int s;	/*服務器套接字文件描述符*/
	struct sockaddr_in server;	/*本地地址*/
	char buff[BUFFLEN];/*收發數據緩衝區*/
	int n = 0;	/*接收字符串長度*/
	
	/*建立TCP套接字*/
	s = socket(AF_INET, SOCK_STREAM, 0);
	
	/*初始化地址接哦股*/
	memset(&server, 0, sizeof(server));/*清零*/
	server.sin_family = AF_INET;/*AF_INET協議族*/
	server.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
	server.sin_port = htons(SERVER_PORT);/*服務器端口*/	
	
	/*連接服務器*/
	int err = connect(s, (struct sockaddr*)&server,sizeof(server));
	memset(buff, 0, BUFFLEN);/*清零*/
	strcpy(buff, "TIME");/*拷貝發送字符串*/
	/*發送數據*/
	send(s, buff, strlen(buff), 0);
	memset(buff, 0, BUFFLEN);/*清零*/
	/*接收數據*/	
	n = recv(s, buff, BUFFLEN, 0);
	/*打印消息*/
	if(n >0){
		printf("TIME:%s\n",buff);	
	}
	close(s);
	
	return 0;		
}
</span>

此模式是最傳統且最普遍常用的併發模型,那麼他也存在缺陷:

1 動態創建也就是臨時創建進程,會增加cpu的開銷(目前此影響不怎麼明顯,可以通過命令ps aux| grep 進程名)

2 如果連接過多,那麼就會創建更多的子進程,會受到系統爲此用戶分配的最大進程數的限制(例如:root用戶爲kevin用戶設置最大開啓100進程數)




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章