고병렬 서버 학습 노트 3: 다중 프로세스 모델

이 모델은 단일 교체 모델을 바탕으로 개선된 것이다. 부모 프로세스는 하나의 죽은 순환에서만 accept를 진행한다. 한 클라이언트가 접속할 때 아버지 프로세스는 하위 프로세스를 포크하고 아버지 프로세스는 연결된 socket을 닫고 계속 accept를 닫는다. 다음 클라이언트가 접속하기를 기다린다. 하위 프로세스는 감청 socket을 닫고 클라이언트의 요청을 처리한다. 처리가 끝난 후에 연결 socket을 닫고 자신의 프로세스를 끝낸다.전체 코드 스탬프 여기
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include  /* superset of previous */
#include 

#include "public_head.h"
#include "fileio.h"

#define LISTEN_BACKLOG 50

static void grim_reaper(int sig)
{
	int saved_error = errno;
	while (waitpid(-1, NULL, WNOHANG) >= 0)
		continue;

	errno = saved_error;
}

static void handle_request(int acceptfd)
{
    int i = 0;
    ssize_t readret = 0;
    char read_buff[256] = { 0 };
    char write_buff[256] = { 0 };
   
	while (1)
	{
		memset(read_buff, 0, sizeof(read_buff));
		readret = read(acceptfd, read_buff, sizeof(read_buff));
		if (readret == 0)
			break;

		printf("progress id:%d, recv message:%s
", getpid(), read_buff); memset(write_buff, 0, sizeof(write_buff)); sprintf(write_buff, "This is server send message:%d", i++); write(acceptfd, write_buff, sizeof(write_buff)); } printf("
"); close(acceptfd); return; } int main(int argc, char ** argv) { pid_t pid; int sockfd = 0; int acceptfd = 0; socklen_t client_addr_len = 0; struct sigaction sa; struct sockaddr_in server_addr, client_addr; char client_ip[16] = { 0 }; memset(&server_addr, 0, sizeof(server_addr)); memset(&client_addr, 0, sizeof(client_addr)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = grim_reaper; if(sigaction(SIGCHLD, &sa, NULL) < 0) handle_error("sigaction"); if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) handle_error("socket"); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(9527); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { char buff[256] = { 0 }; close(sockfd); strerror_r(errno, buff, sizeof(buff)); handle_error("bind"); } if(listen(sockfd, LISTEN_BACKLOG) < 0) { close(sockfd); handle_error("listen"); } while(1) { client_addr_len = sizeof(client_addr); if((acceptfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) { handle_warning("accept"); continue; } memset(client_ip, 0, sizeof(client_ip)); inet_ntop(AF_INET,&client_addr.sin_addr,client_ip,sizeof(client_ip)); printf("client:%s:%d
",client_ip,ntohs(client_addr.sin_port)); pid = fork(); if (pid > 0) //parent { close(acceptfd); continue; } else if (pid == 0) //child { close(sockfd); handle_request(acceptfd); exit(EXIT_SUCCESS); } else { handle_warning("fork"); continue; } } close(sockfd); exit(EXIT_SUCCESS); }

좋은 웹페이지 즐겨찾기