1 / 66

11 장 동시 클라이언트 서버

11 장 동시 클라이언트 서버. Program language Lab. 김 병 규. 11 장 . 동시 클라이언트 서버. 목차 11.1 멀티플 클라이언트 문제의 이해 11.2 서버 함수의 개요 11.3 fork 를 사용한 멀티플 클라이언트 서비스 11.4 select(2) 를 사용한 서버 설계 11.5 select(2) 를 적용한 서버. 11 장 동시 클라이언트 서버 . 이장의 목표 다양한 클라이언트 연결을 다루기 위한 fork(2) 함수

rafael
Download Presentation

11 장 동시 클라이언트 서버

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 11장 동시 클라이언트 서버 Program language Lab. 김 병 규

  2. 11장. 동시 클라이언트 서버 목차 • 11.1 멀티플 클라이언트 문제의 이해 • 11.2 서버 함수의 개요 • 11.3 fork 를 사용한 멀티플 클라이언트 서비스 • 11.4 select(2) 를 사용한 서버 설계 • 11.5 select(2) 를 적용한 서버

  3. 11장 동시 클라이언트 서버 • 이장의 목표 • 다양한 클라이언트 연결을 다루기 위한 fork(2) 함수 • Wait and waitpid 함수 • 멀티 클라이언트 연결을 다루기 위한 select(2) 함수

  4. 11.1 멀티플 클라이언트 문제의 이해 Client Client Client Server Client Client Client

  5. 11.1 멀티플 클라이언트 문제의 이해 • Forked server processes (multi-process method) • Threaded server processes [multi-process method) • One process and a select(2) call • One process and a poll(2) call

  6. 11.1 멀티플 클라이언트 문제의 이해 • Fork • 멀티플 클라이언트 프로세서를 처리해 주는 가장 간단한 방법 • 정보 공유시 복잡해짐 • 메시지큐의 사용과 메모리 공유 서마포어 요구 • 시작시 많은 CPU 요구 and 각 요청마다 새로운 프로세스 생성 • Thread • Kernel version 2.0.0 이후 버전 채용 • 스레드 라이브러리 사용 • 가볍고 장점 있는 멀티 process 메소드 제공 • 디버깅 하기 어려움

  7. 11.2 서버 함수의 개요 Table 11.1: 기본 RPN Server 함수들 함수 인수 설명 # interger 정수 값을 스택에 푸쉬 한다. + n/a 스택의 탑에 있는 두 숫자를 더한다. 결과값을 다시 스택에 갖다 놓는다. - n/a 스택의 탑에 있는 값에서 그 다음에 있는 값을 뺀 후 결과값을 스택에 다시 놓는다. * n/a 스택의 탑에 값에서 그 다음 값을 곱 한 후 결과값을 다시 스택에 놓는다.

  8. 11.2 서버 함수의 개요 Table 11.1: 기본 RPN Server 함수들 함수 인수 설명 / n/a 스택의 탑에 있는 값에서 그 다음 값 을 나눈 후 결과값을 스택에 다시 갖 다 놓는다. % n/a 스택의 탑에 있는 두 숫자를 나눈 후 나머지를 다시 스택의 탑에 넣는다. = n/a 결과를 빼내서 클라이언트에 돌려준다. Dump n/a 전체 스택을 비워서 클라이언트에 돌려준다. 스택은 변경돼지 않는다.

  9. 11.2 서버 함수의 개요 Table 11.2: 1진법 RPN Server 함수들 함수 인수 설명 abs n/a 스택의 탑에 있는 값을 절대값으로 재위치 시킨다. neg n/a 스택 탑의 값을 음수로 바꾸어준다음 재 위치 시킨다. sqrt n/a 스택 탑의 값을 정수 제곱근으로 재위치 시킨다.

  10. 11.2 서버 함수의 개요 Table 11.3: 진보된 RPN Server 함수들 함수 인수 설명 gcd n/a 스택에 있는 두수의 최대 공약수를 계산해 준다. 결과값은 스택에 재위치 시킨다. seed n/a 스택 탑의 값을 사용하여 무작위 seed 값을 만들어 내고 결과 값을 스택에 푸쉬 시키진 않는다. random n/a 탑 스택에 있는 값을 사용하여 가장 큰값 + 1 안에서 랜덤 숫자를 생성해 낸다. 랜덤 결과는 스택에 재위치 입 력된다.

  11. 11.2 서버 함수의 개요 Table 11.3: 진보된 RPN Server 함수들 함수 인수 설명 tprime n/a 스택 탑에 있는 값이 소수인지 테스 트한다. 2~ 마지막 숫자까지 표시하 여테스트를 적용한다. 전형적인 값은 25이다. 결과값 1을 재위치 1은 소수 0은 소수가 아님 genprime n/a 소수를 만들어 낸다. 스택 탑에 값을 사용하여 최대 무작위 숫자+1값을 스택에서 두번째 마지막 숫자까지 지시하는 숫자를 테스트 실행

  12. 11.2 서버 함수의 개요 Table 11.3: 진보된 RPN Server 함수들 함수 인수 설명 swap n/a 스택 위의 두 숫자를 바꾼다. 편리한 방법은 두 숫자를 교환 하는 거다. dup n/a 스택 탑의 값을 복제한다. • seed 와 random 함수 사용시 비트의 해석이 요구

  13. 11.2 RPN 서버 + 7 2: 2: * 2: 1: 4 1: 11 1: 0: 3 0: 3 0: 33

  14. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 목차 11.3.1 서버 프로세스의 종합적인 이해 11.3.2 자식 프로세스 흐름의 이해 11.3.3 프로세스 종료처리의 이해

  15. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 용도 1. 프로세스는 자신의 복사본을 만들어서 각기 다른 일을 처리하게 한다. 2. 프로세스가 다른 프로그램을 수행한다. fork 를 부르는 것이 새 프로세스를 만드는 유일한 방법. 프로세스는 먼저 fork 를 호출하여 복사본 만든다.

  16. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 서버 프로세스의 종합적인 이해 • 신호 조작자 설치 (79) signal(SIGCHLD, sigchld_handler); • 서버 주소와 소켓을 만듬 (85~112) if ( argc >= 2 ) srvr_addr = argv[1]; len_inet = sizeof adr_srvr; z = mkaddr(&adr_srvr,&len_inet, srvr_addr,"tcp");

  17. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 s = socket(PF_INET,SOCK_STREAM,0); 소켓생성 z = bind(s,(struct sockaddr *)&adr_srvr, bind 반복 listen z = listen(s,10); c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet); accept 포크 호출 자식 생성 if ( (PID = fork()) == -1 ) fork rx = fdopen(c,"r"); , tx =fdopen(dup(c),"w"); Stream 생성

  18. while ( fgets(buf,sizeof buf,rx) ) rpn_process(tx,buf); 클라이언트 요청 처리 fclose(tx); shutdown(fileno(rx),SHUT_RDWR); fclose(rx); 클라이언트 연결을 닫음 Exit(0); 종료

  19. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 서버 프로세스의 종합적인 이해 if ( z < 0 || !adr_srvr.sin_port ) { fprintf(stderr,"Invalid server " "address, or no port number " "was specified.\n"); exit(1); }

  20. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 • Tcp/ip 소켓 create s = socket(PF_INET,SOCK_STREAM,0); if ( s == -1 ) bail("socket(2)"); • 서버주소 연결 z = bind(s,(struct sockaddr *)&adr_srvr, len_inet); if ( z == -1 ) bail("bind(2)");

  21. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 소켓을 리스닝 소켓 으로 바꿈 (117~119) z = listen(s,10); if ( z == -1 ) bail("listen(2)"); 메인 루프 시작, 서버 블록을 client 에 연결할 때까지 실행 (124) for (;;) { len_inet = sizeof adr_clnt; c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet); if ( c == -1 ) bail("accept(2)");

  22. 11.3 fork 를 사용한 멀티플 클라이언트 서비스 Fork 호출 (139) if ( (PID = fork()) == -1 ) { /* Failed to fork: Give up */ close(c); continue; } else if ( PID > 0 ) { /* Parent process: */ 부모 프로세스 닫음 close(c); continue; } 실패시 –1을 돌려줌 서버는 소켓c 를 닫음 pt18부터 다시 시작 성공시 pid는 부모 프로세스로부터 자식 프로세스 id 를 내포 부모 프로세스는 c로 연결을 받고 닫음 그리고 pt18부터 다시시작

  23. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 자식 프로세스 흐름의 이해 • 자식 프로세스는 스텝 6에서 fork 에 의해 생성 • Fork 함수는 자식 프로세스 로 부터 0을 리턴(153~164) rx = fdopen(c,"r"); if ( !rx ) { /* 자식 프로세스는 계속해서 close(c); 소켓 c를 열고 이 소켓을 continue; } 파일 스트림 rx and tx를 tx = fdopen(dup(c),"w"); 연관시킨다 */ if ( !tx ) { fclose(rx); continue; }

  24. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 자식 프로세스 –계속 (170~184) setlinebuf(rx); setlinebuf(tx); while ( fgets(buf,sizeof buf,rx) ) //Process client's requests : rpn_process(tx,buf); // Close this client's connection fclose(tx); shutdown(fileno(rx),SHUT_RDWR); fclose(rx);

  25. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 • 자식 프로세스는 클라이언트로부터 마지막으로 프로세싱됨 exit 함수 호출로 자식 프로세스 종료 exit(0); • 이과정은 부모 프로세스에서 signal SIHCHLD증가 시키는 원인 • PT 19에서 부모 프로세스는 소켓 C를 닫음 • 포크 호출후 부모 클라이언트 프로세서 둘다에 소켓을 열기 떄문에 중요

  26. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 • 부모 서버 프로세스 실행 단계 • 클라이언트 연결을 받아들임 • Fork 새로운 프로세스를 클라이언트에게 서비스 해준다. • 연결된 클라이언트 소켓을 복사한 후 닫는다. • 1단계부터 반복

  27. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 sigchld sigchld sigchld sigchld exit client Server parent Server child#1 Server child#2 Server child#3 Server child#4 3 2 1 0 fin fin fin fin

  28. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 프로세스 종료 처리의 이해 • 신호 SIGCHLD 는 커널이 가리키는 자식 프로세스를 종료시킨다. 신호 SIGCHLD 는 커널에 의해 증가 • 함수 sigchld_handler()를 호출 sigchld_handler(int signo) { 호출 이유는 라인 79에 등록돼 있기 때문 signal(SIGCHLD,sigchld_handler);

  29. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 프로세스 종료 처리의 이해 SIGCHLD handler 원래 대로 회복 (44) /* Re-instate handler */ signal(SIGCHLD,sigchld_handler);

  30. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 프로세스 종료 처리의 이해 3.함수 sigchld_handler() 함수 실행 sigchld_handler(int signo) { pid_t PID; int status; do { PID = waitpid(-1,&status,WNOHANG); } while ( PID != -1 ); 종료 되지 않은 자식이 실행중이면 waitpid가 봉쇄되지 않도록함 작업중인 자식 프로세스가 있으면 봉쇄 되도록 함

  31. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 server client listenfd Connect() Accept 호출전의 서버와 클라이언트 상태 client Server (parent) Connect() listenfd connfd Accept에서 돌아온 후의 클라이언트-서버 상태 server client listenfd Connect() Server (child) connfd Fork에서 돌아온 후의 클라이언트-서버 상태

  32. 11.3 fork 를 이용한 멀티플 클라이언트 서비스 메모 • Production 모드 서버는 신호 함수 sigaction(2) 를 사용해야한다 • 포크함수가 wait waitpid 호출이 실패하면 자식 프로세스가 후에 종료되어 결과적으로 부모 프로세스가 종료 될 때까지 좀비프로세스가 생겨난다.

  33. 11.4 select(2) 를 사용한 서버 설계 Select 함수의 소개 • 프로세스가 kernel에게 여러 사건 중에서 하나이상이 발생할 때까지 기다리다가 하나 이상의 사건이 발생하거나 또는 지정된 시간이 경과할 때만 프로세스를 깨우라고 지시 • 서버가 어떤 일을 하는 동안 블록 실행을 하는것을 허락해 줌 #include <sys/select.h> #include <sys/time.h> Int select(int maxfdp1, fd_set *readset , fd_set *writeset , fd_set *exceptset, const struct timeval * timeout);

  34. Select (2)함수를 사용한 서버 설계 Select 인수 1. 최대 숫자(n)파일기술자에서 테스트. 값은 적어도 최대 파일 기술자 숫자 + 1, 후에 파일기술자는 0에서 시작 2. 파일 기술자 집합(readfds) 읽는 자료로부터 테스트 3. 파일 기술자 집합(writefds) 쓰기 가능 으로부터 테스트 4. 파일 기술자 집합(exceptfds) 예외에 관한 테스트. 5. 포인터 timeout 요구는 함수 호출을 선정, 포인터가 null 이면 no timeout 을 지시한다.

  35. Select (2)함수를 사용한 서버 설계 select 함수 리턴값 -1 함수 호출에 에러 발생 0 아무것도 발생하지 않고 timeout 시 0 보다 큰 숫자는 파일기술자가 무언가를 생성 Timeval 구조 struct timeval { long tv_sec; long tv_use; };

  36. Select (2)함수를 사용한 서버 설계 파일 기술자 집합 다루기 FD_ZERO(fd_set *set); FD_SET(int fd, fd_set *set); FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); C 매크로는 너가 파일 기술자 집합을 다루는걸 허락해준다.

  37. Select (2)함수를 사용한 서버 설계 • FD_ZERO macro 사용법 • 파일 기술자 집합을 초기화, 파일 기술자 등록전에 • 집합을 모두 0bit 로 초기화 해야 한다. fd_set read_sock; fd_set write_sock; FD_ZERO(&read_socks); FD_ZERO(&write_socks);

  38. Select (2)함수를 사용한 서버 설계 • FD_SET 매크로 사용법 FD_ZERO매크로로 파일 기술자를 초기화 한후 FD_SET 매크로로 원하는 파일 기술자를 등록 시킬 수 있다. int c; /*client socket */ fd_set read_socks; /* read set */ FD_SET(c, &read_socks); Fd_set 호출 후 bit 등록 시 파일 기술자와 함께 참조 집합을 교신

  39. Select (2)함수를 사용한 서버 설계 • FD_CLR 매크로 사용법 이 C 매크로는 FD_SET 매크로의 효과를 원래대로 되돌린다. 소켓 C 를 한번 다시 떠 맡는다. int c; /* client socket */ fd_set read_socks; /* read set */ FD_CLR(c, &read_socks); Fd 매크로가 가지는 효과는 제로를 bit 연동시켜 파일 기술자에 재전송하는 것이다. FD_ZERO와는 다름 , 이것은 단지 파일 기술자 집합을 명확하게 클리어 시키는 것이다.

  40. Select (2)함수를 사용한 서버 설계 FD_ISSET 매크로와 파일 기술자 시험 동시에 테스트하면 만약 특별한 파일 기술자는 집합을 함께 제출한다. 만약 그것이 집합 비트로 연결시 int c; /* client socket */ fd_set read_socks; /* read set */ … if(FD_ISSET(c, &read_socks) ) { … } else { … /* socket c is not in the set */ }

  41. Select (2)함수를 사용한 서버 설계 • 소켓 c 집합인지 아닌지 테스트한다. • If 절은 매크로 fd_isset 이 소켓c 가 출력하는 파일 기술자 집합 read_sock을 테스트하는걸 보여준다. • 만약 테스트 리턴 값이 트루 라면 소켓C 는 그것에 대응하는 비트 집합을 ENABLE 하고 첫번째 블록 C CODE 를 실행한다.

  42. Select (2)함수를 사용한 서버 설계 Int select(int maxfdp1, &rx_set , fd_set*writeset , fd_set *exceptset, const struct timeval * timeout); FD_ZERO(&rx_set); 초기화 FD_SET(s,&rx_set); Turn on bit FD_ISSET(z,&rx_set) test FD_CLR(c,&rx_set); clear

  43. 11.5 select(2) 를 적용한 서버 수정된 rpneng.c 엔진 *** 18,25 **** -- 18,25 ---- * RPN Stack : * RPN Stack : #define MAX_STACK 32 #define MAX_STACK 32 ! static mpz_t *stack[MAX_STACK]; ! mpz_t **stack; ! static int sp = 0; ! int sp = 0; *** 45,51 **** --- 45,51 ---- //Free an allocated mpz_t value : //Free an allocated mpz_t value : ! static void ! void rpn_free(mpz_t **v) { rpn_free(mpz_t **v) { mpz_clear(**v); mpz_clear(**v); free(*v); free(*v);

  44. 11.5 select(2) 를 적용한 서버 서버 초기화와 새로운 연결을 받는 과정 s = socket(PF_INET,SOCK_STREAM,0); 소켓생성 z = bind(s,(struct sockaddr *)&adr_srvr, bind listen z = listen(s,10); n = select(mx,&wk_set,NULL,NULL,&tv); Select c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet); accept rx = fdopen(c,"r"); , tx =fdopen(dup(c),"w"); Stream 생성

  45. 11.5 select(2) 를 적용한 서버 client[c].sp = 0; client[c].stack = (mpz_t **) malloc(sizeof (mpz_t *) * MAX_STACK); 스택 초기화 자식 프로세스 처리 rpn_process(tx,buf); Exit(0); 종료

  46. 11.5 select(2) 를 적용한 서버 프로그램 개요구조 시험 Include <sys/time.h> 에 timeval 자료구조 정의 들어감 (line 12) rpn_free 함수 프로토 타입 정의 (line 33) extern void rpn_free(mpz_t **v); 맥스 스택 매크로 정의 #define MAX_STACK 32 서버에서 지원되는 클라이언트 프로세서 의 최대수 정의 #define MAX_CLIENTS 64 외부 선언된 스택과 sp (line41,42) extern mpz_t **stack; extern int sp;

  47. 11.5 select(2) 를 적용한 서버 프로그램 개요구조 시험 각 클라이언트에 관한 정보는 자료 유형 clientinfo에 의하여 이프로그램 안에 유지된다. (47~52) typedef struct { mpz_t **stack; /* Stack Array */ int sp; /* Stack ptr */ FILE *rx; /* Recv FILE */ FILE *tx; /* Xmit FILE */ } ClientInfo; ClientInfo client[MAX_CLIENTS];

  48. 11.5 select(2) 를 적용한 서버 새로운 클라이언트 처리 함수 정의 (74~116) process_client(int c) { char buf[4096]; /* I/O Buffer */ FILE *rx = client[c].rx; FILE *tx = client[c].tx; stack = client[c].stack; // Install correct RPN stack : sp = client[c].sp; if ( !feof(rx) && fgets(buf,sizeof buf,rx) ) //If not EOF, process one line : rpn_process(tx,buf); if ( !feof(rx) ) { /* Save SP and exit */ client[c].sp = sp; return 0; }

  49. 11.5 select(2) 를 적용한 서버 첫번째 값 n 정의 (130) int n; /* return val from select(2) */ n은 207에서 select(2) 호출로부터 리턴값을 갖는다. n = select(mx,&wk_set,NULL,NULL,&tv); 최대 파일 기술자 변수 mx (131) int mx; /* Max fd + 1 */ 파일 기술자 집합 rx_set, wk_set 정의 fd_set rx_set; /* Read set */ fd_set wk_set; /* Working set */ timeout 값 구조 tv 정의 (134) struct timeval tv; /* Timeout value */

  50. 11.5 select(2) 를 적용한 서버 메인 프로그램 흐름 분석 1.루프를 위한 ClientInfo 배열 client() 초기화 (139~144) for ( z=0; z<MAX_CLIENTS; ++z ) { client[z].stack = NULL; client[z].sp = 0; client[z].rx = NULL; client[z].tx = NULL; } 2. Create 소켓 bind 호출 listen 호출 (150~184) s = socket(PF_INET,SOCK_STREAM,0); z = bind(s,(struct sockaddr *)&adr_srvr, len_inet); z = listen(s,10);

More Related