11 장 동시 클라이언트 서버

66
1 HANNAM UNIVERSITY Http://netwk.hannam.ac.kr 11 11 장 장장 장장장장장 장장 장 장장 장장장장장 장장 Program language Lab. 장 장 장

Upload: rafael

Post on 05-Jan-2016

101 views

Category:

Documents


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: 11 장 동시 클라이언트 서버

1HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

1111 장 동시 클라이언트 서버장 동시 클라이언트 서버

Program language Lab. 김 병 규

Page 2: 11 장 동시 클라이언트 서버

2HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

1111 장장 . . 동시 클라이언트 서버동시 클라이언트 서버

목차

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

Page 3: 11 장 동시 클라이언트 서버

3HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

1111 장 동시 클라이언트 서버장 동시 클라이언트 서버

이장의 목표

다양한 클라이언트 연결을 다루기 위한 fork(2) 함수

Wait and waitpid 함수멀티 클라이언트 연결을 다루기 위한 select(2)

함수

Page 4: 11 장 동시 클라이언트 서버

4HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.1 11.1 멀티플 클라이언트 문제의 이해멀티플 클라이언트 문제의 이해

Server

ClientClient Client

Client Client Client

Page 5: 11 장 동시 클라이언트 서버

5HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.1 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

Page 6: 11 장 동시 클라이언트 서버

6HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.1 11.1 멀티플 클라이언트 문제의 이해멀티플 클라이언트 문제의 이해

Fork 멀티플 클라이언트 프로세서를 처리해 주는 가장 간단한

방법 정보 공유시 복잡해짐 메시지큐의 사용과 메모리 공유 서마포어 요구 시작시 많은 CPU 요구 and 각 요청마다 새로운 프로세스

생성 Thread

Kernel version 2.0.0 이후 버전 채용 스레드 라이브러리 사용 가볍고 장점 있는 멀티 process 메소드 제공 디버깅 하기 어려움

Page 7: 11 장 동시 클라이언트 서버

7HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 11.2 서버 함수의 개요서버 함수의 개요

Table 11.1: 기본 RPN Server 함수들함수 인수 설명# interger 정수 값을 스택에 푸쉬 한다 .+ n/a 스택의 탑에 있는 두 숫자를 더한다 .

결과값을 다시 스택에 갖다 놓는다 .- n/a 스택의 탑에 있는 값에서 그 다음에

있는 값을 뺀 후 결과값을 스택에 다시 놓는다 .

* n/a 스택의 탑에 값에서 그 다음 값을 곱 한 후 결과값을 다시 스택에 놓는다 .

Page 8: 11 장 동시 클라이언트 서버

8HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 11.2 서버 함수의 개요서버 함수의 개요

Table 11.1: 기본 RPN Server 함수들함수 인수 설명/ n/a 스택의 탑에 있는 값에서 그 다음 값

을 나눈 후 결과값을 스택에 다시 갖 다 놓는다 .

% n/a 스택의 탑에 있는 두 숫자를 나눈 후 나머지를 다시 스택의 탑에 넣는다 .

= n/a 결과를 빼내서 클라이언트에 돌려준다 .

Dump n/a 전체 스택을 비워서 클라이언트에 돌려준다 . 스택은 변경돼지

않는다 .

Page 9: 11 장 동시 클라이언트 서버

9HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 11.2 서버 함수의 개요서버 함수의 개요

Table 11.2: 1 진법 RPN Server 함수들함수 인수 설명abs n/a 스택의 탑에 있는 값을 절대값으로

재위치 시킨다 .neg n/a 스 택 탑 의 값 을 음 수 로

바꾸어준다음 재 위치 시킨다 .sqrt n/a 스택 탑의 값을 정수 제곱근으로

재위치 시킨다 .

Page 10: 11 장 동시 클라이언트 서버

10HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 11.2 서버 함수의 개요서버 함수의 개요

Table 11.3: 진보된 RPN Server 함수들함수 인수 설명gcd n/a 스택에 있는 두수의 최대 공약수를

계산해 준다 . 결과값은 스택에 재위치 시킨다 .

seed n/a 스택 탑의 값을 사용하여 무작위 seed 값을 만들어 내고

결과 값을 스택에 푸쉬 시키진 않는다 .random n/a 탑 스택에 있는 값을 사용하여 가장

큰값 + 1 안에서 랜덤 숫자를 생성해 낸다 . 랜덤 결과는 스택에 재위치 입 력된다 .

Page 11: 11 장 동시 클라이언트 서버

11HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 11.2 서버 함수의 개요서버 함수의 개요

Table 11.3: 진보된 RPN Server 함수들함수 인수 설명tprime n/a 스택 탑에 있는 값이 소수인지 테스

트한다 . 2~ 마지막 숫자까지 표시하 여테스트를 적용한다 . 전형적인 값은 25 이다 . 결과값 1 을 재위치 1 은 소수 0 은 소수가 아님

genprime n/a 소수를 만들어 낸다 . 스택 탑에 값을 사용하여 최대 무작위 숫자 +1 값을 스택에서 두번째 마지막 숫자까지

지시하는 숫자를 테스트 실행

Page 12: 11 장 동시 클라이언트 서버

12HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 11.2 서버 함수의 개요서버 함수의 개요

Table 11.3: 진보된 RPN Server 함수들함수 인수 설명swap n/a 스택 위의 두 숫자를 바꾼다 . 편리한

방법은 두 숫자를 교환 하는 거다 .dup n/a 스택 탑의 값을 복제한다 .

seed 와 random 함수 사용시 비트의 해석이 요구

Page 13: 11 장 동시 클라이언트 서버

13HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.2 RPN 11.2 RPN 서버서버

34

7

0:

1:2:

+

311

0:

1:2:

330:

1:2:

*

Page 14: 11 장 동시 클라이언트 서버

14HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 사용한 멀티플 클라이언트 를 사용한 멀티플 클라이언트 서비스 서비스

목차

11.3.1 서버 프로세스의 종합적인 이해 11.3.2 자식 프로세스 흐름의 이해 11.3.3 프로세스 종료처리의 이해

Page 15: 11 장 동시 클라이언트 서버

15HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 사용한 멀티플 클라이언트 를 사용한 멀티플 클라이언트 서비스 서비스

용도

1. 프로세스는 자신의 복사본을 만들어서 각기 다른 일을 처리하게 한다 .

2. 프로세스가 다른 프로그램을 수행한다 . fork 를 부르는 것이 새 프로세스를 만드는 유일한 방법 . 프로세스는 먼저 fork 를 호출하여 복사본

만든다 .

Page 16: 11 장 동시 클라이언트 서버

16HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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");

Page 17: 11 장 동시 클라이언트 서버

17HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 사용한 멀티플 클라이언트 를 사용한 멀티플 클라이언트 서비스 서비스

s = socket(PF_INET,SOCK_STREAM,0);

소켓생성

z = bind(s,(struct sockaddr *)&adr_srvr, bind

z = listen(s,10); listen

c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet); accept

rx = fdopen(c,"r"); , tx =fdopen(dup(c),"w");

fork 포크 호출 자식 생성

if ( (PID = fork()) == -1 )

Stream 생성

반복

Page 18: 11 장 동시 클라이언트 서버

18HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Exit(0); 종료

클라이언트 요청 처리while ( fgets(buf,sizeof buf,rx) )

rpn_process(tx,buf);

fclose(tx); shutdown(fileno(rx),SHUT_RDWR);

fclose(rx);클라이언트 연결을 닫음

Page 19: 11 장 동시 클라이언트 서버

19HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 사용한 멀티플 클라이언트 를 사용한 멀티플 클라이언트 서비스 서비스

서버 프로세스의 종합적인 이해

if ( z < 0 || !adr_srvr.sin_port ) { fprintf(stderr,"Invalid server " "address, or no port number "

"was specified.\n"); exit(1); }

Page 20: 11 장 동시 클라이언트 서버

20HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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)");

Page 21: 11 장 동시 클라이언트 서버

21HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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)");

Page 22: 11 장 동시 클라이언트 서버

22HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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 부터

다시시작

Page 23: 11 장 동시 클라이언트 서버

23HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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; }

Page 24: 11 장 동시 클라이언트 서버

24HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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);

Page 25: 11 장 동시 클라이언트 서버

25HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스서비스

자식 프로세스는 클라이언트로부터 마지막으로 프로세싱됨

exit 함수 호출로 자식 프로세스 종료 exit(0);

이과정은 부모 프로세스에서 signal SIHCHLD증가 시키는 원인

PT 19 에서 부모 프로세스는 소켓 C 를 닫음 포크 호출후 부모 클라이언트 프로세서 둘다에

소켓을 열기 떄문에 중요

Page 26: 11 장 동시 클라이언트 서버

26HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스 서비스

부모 서버 프로세스 실행 단계

1. 클라이언트 연결을 받아들임2. Fork 새로운 프로세스를 클라이언트에게 서비스

해준다 .3. 연결된 클라이언트 소켓을 복사한 후 닫는다 .4. 1 단계부터 반복

Page 27: 11 장 동시 클라이언트 서버

27HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스 서비스

client exit

3 2 1 0

Server parent

Server child#

1

Server child#

2

Server child#

3

Server child#

4

finfin

fin

fin

sigchldsigchld

sigchld

sigchld

Page 28: 11 장 동시 클라이언트 서버

28HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스 서비스

프로세스 종료 처리의 이해

1. 신호 SIGCHLD 는 커널이 가리키는 자식 프로세스를 종료시킨다 . 신호 SIGCHLD 는 커널에 의해 증가

2. 함수 sigchld_handler() 를 호출 sigchld_handler(int signo) { 호출 이유는 라인 79 에 등록돼 있기 때문 signal(SIGCHLD,sigchld_handler);

Page 29: 11 장 동시 클라이언트 서버

29HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스 서비스

프로세스 종료 처리의 이해 SIGCHLD handler 원래 대로 회복 (44) /* Re-instate handler */ signal(SIGCHLD,sigchld_handler);

Page 30: 11 장 동시 클라이언트 서버

30HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 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 가 봉쇄되지

않도록함

작업중인 자식 프로세스가 있으면 봉쇄 되도록 함

Page 31: 11 장 동시 클라이언트 서버

31HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스 서비스

•listenfdserve

rclient

Connect()

Accept 호출전의 서버와 클라이언트 상태

listenfd

connfd

Server (parent) Connect()

client

Accept 에서 돌아온 후의 클라이언트 - 서버 상태serve

r•listenfd Connect()

client

connfd

Server (child)

Fork 에서 돌아온 후의 클라이언트 - 서버 상태

Page 32: 11 장 동시 클라이언트 서버

32HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.3 fork 11.3 fork 를 이용한 멀티플 클라이언트 를 이용한 멀티플 클라이언트 서비스 서비스

메모

Production 모드 서버는 신호 함수 sigaction(2) 를 사용해야한다

포크함수가 wait waitpid 호출이 실패하면 자식 프로세스가 후에 종료되어 결과적으로 부모 프로세스가 종료 될 때까지 좀비프로세스가 생겨난다 .

Page 33: 11 장 동시 클라이언트 서버

33HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.4 select(2) 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);

Page 34: 11 장 동시 클라이언트 서버

34HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)Select (2) 함수를 사용한 서버 설계함수를 사용한 서버 설계

Select 인수 1. 최대 숫자 (n)파일기술자에서 테스트 . 값은 적어도 최대 파일 기술자 숫자 + 1, 후에 파일기술자는 0 에서 시작 2. 파일 기술자 집합 (readfds) 읽는 자료로부터 테스트 3. 파일 기술자 집합 (writefds) 쓰기 가능 으로부터

테스트 4. 파일 기술자 집합 (exceptfds) 예외에 관한 테스트 . 5. 포인터 timeout 요구는 함수 호출을 선정 , 포인터가 null 이면 no timeout 을 지시한다 .

Page 35: 11 장 동시 클라이언트 서버

35HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)Select (2) 함수를 사용한 서버 설계함수를 사용한 서버 설계

select 함수 리턴값 -1 함수 호출에 에러 발생 0 아무것도 발생하지 않고 timeout 시 0 보다 큰 숫자는 파일기술자가 무언가를 생성

Timeval 구조 struct timeval { long tv_sec;

long tv_use; };

Page 36: 11 장 동시 클라이언트 서버

36HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)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 매크로는 너가 파일 기술자 집합을 다루는걸 허락해준다 .

Page 37: 11 장 동시 클라이언트 서버

37HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)Select (2) 함수를 사용한 서버 설계함수를 사용한 서버 설계

FD_ZERO macro 사용법파일 기술자 집합을 초기화 , 파일 기술자 등록전에 집합을 모두 0bit 로 초기화 해야 한다 .

fd_set read_sock; fd_set write_sock; FD_ZERO(&read_socks); FD_ZERO(&write_socks);

Page 38: 11 장 동시 클라이언트 서버

38HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)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 등록 시 파일 기술자와 함께 참조 집합을

교신

Page 39: 11 장 동시 클라이언트 서버

39HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)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 와는 다름 , 이것은 단지 파일 기술자 집합을

명확하게 클리어 시키는 것이다 .

Page 40: 11 장 동시 클라이언트 서버

40HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)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 */ }

Page 41: 11 장 동시 클라이언트 서버

41HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)Select (2) 함수를 사용한 서버 설계함수를 사용한 서버 설계

소켓 c 집합인지 아닌지 테스트한다 . If 절은 매크로 fd_isset 이 소켓 c 가 출력하는 파일

기술자 집합 read_sock 을 테스트하는걸 보여준다 . 만약 테스트 리턴 값이 트루 라면 소켓 C 는 그것에

대응하는 비트 집합을 ENABLE 하고 첫번째 블록 C CODE 를 실행한다 .

Page 42: 11 장 동시 클라이언트 서버

42HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

Select (2)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

Page 43: 11 장 동시 클라이언트 서버

43HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 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);

Page 44: 11 장 동시 클라이언트 서버

44HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버s =

socket(PF_INET,SOCK_STREAM,0);소켓생성

z = bind(s,(struct sockaddr *)&adr_srvr, bind

z = listen(s,10); listen

c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet); accept

rx = fdopen(c,"r"); , tx =fdopen(dup(c),"w");

Selectn = select(mx,&wk_set,NULL,NULL,&tv);

Stream 생성

서버

초기화와

새로운

연결을

받는

과정

Page 45: 11 장 동시 클라이언트 서버

45HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

rpn_process(tx,buf);

Exit(0); 종료

자식 프로세스 처리

client[c].sp = 0; client[c].stack =

(mpz_t **) malloc(sizeof (mpz_t *) * MAX_STACK);

스택 초기화

Page 46: 11 장 동시 클라이언트 서버

46HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 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;

Page 47: 11 장 동시 클라이언트 서버

47HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 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];

Page 48: 11 장 동시 클라이언트 서버

48HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 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; }

Page 49: 11 장 동시 클라이언트 서버

49HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 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 */

Page 50: 11 장 동시 클라이언트 서버

50HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버메인 프로그램 흐름 분석1. 루프를 위한 ClientInfo 배열 client() 초기화 (139~1

44) 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);

Page 51: 11 장 동시 클라이언트 서버

51HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버3.rx_set초기화 (190) rx_set 은 읽기 이벤트시 주된 소켓 집합 FD_ZERO(&rx_set); /* Init. */

4. 파일 기술자 집합 rx_set 으로 소켓 s 를 입력해 fd_set매크로 호출 (191)

FD_SET(s,&rx_set); /* + s */연결될 이소켓에 읽기 이벤트가 일어나 select 응답이 옴

5. 변수 mx s+1 로 초기화 mx = s + 1; /* max fd + 1 */

6. 서버 루프 시작 (197)

Page 52: 11 장 동시 클라이언트 서버

52HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

7.fd_zero 매크로로 wk_set 파일 기술자 집합 호출 (201) FD_ZERO(&wk_set);

비트를 0 으로 클리어 wk_set 은 이프로그램을 위해 워킹 세트로서 작동한다 . select(2) 이 그것을 통과하면서 수정 (202~205)

8. 파일 기술자 rx_set 안의 작업집합을 wk_set 으로 카피 for ( z=0; z<mx; ++z ) { if ( FD_ISSET(z,&rx_set) ) FD_SET(z,&wk_set);

}

Page 53: 11 장 동시 클라이언트 서버

53HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

9. 타임아웃 값 설정 (210~211) tv.tv_sec = 2; tv.tv_usec = 30000;

10.select 함수 호출 (213) 리턴값으로 변수 n 할당 n = select(mx,&wk_set,NULL,NULL,&tv);

11. 에러 발생 감지 (214) if ( n == -1 ) { fprintf(stderr,"%s: select(2)\n", strerror(errno)); exit(1);

Page 54: 11 장 동시 클라이언트 서버

54HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

12.timeout 발생 (218~220) } else if ( !n ) { /* puts("Timeout."); */ continue; }

13.FD_ISSET 매크로 사용 WK_SET 집합안의 소켓 S 테스트 (226) if ( FD_ISSET(s,&wk_set) ) { 14. 값이 트루일 경우 클라이언트 연결을 accept (230~235) len_inet = sizeof adr_clnt; c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet);

Page 55: 11 장 동시 클라이언트 서버

55HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

15. 클라이언트 연결 처리 if ( c >= MAX_CLIENTS ) { close(c); /* At capacity */

16.파일 스트림 rx 및 tx 생성 버퍼링 모드 생성 client[c].rx = fdopen(c,"r"); if ( !client[c].rx ) { close(c); /* Failed */ continue; } client[c].tx = fdopen(dup(c),"w"); if ( !client[c].tx ) { fclose(client[c].rx); continue; }

Page 56: 11 장 동시 클라이언트 서버

56HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버클라이언트 연결 처리 - 계속 if ( c + 1 > mx ) mx = c + 1;

setlinebuf(client[c].rx); * Set both streams to line setlinebuf(client[c].tx); * buffered mode :

17. 클라이언트 기입을 위해 클라이언트 초기화 및 스택 할당 client[c].sp = 0; client[c].stack = (mpz_t **) malloc (sizeof (mpz_t *) * MAX_STACK);

Page 57: 11 장 동시 클라이언트 서버

57HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버wk_set 테스트

최대 파일 기술자 만큼 반복

클라이언트 처리

FD_CLR(C , &rx_set); clear

읽기 가능한지 테스트

if ( FD_ISSET(s,&wk_set) )

for ( c=0; c<mx; ++c ) { 받아 들인 소켓 s 만큼 처리 mx = s +1

if ( c == s )

continue;

s 는 .. listening socke

•c 는 client socket듣는 소켓 추려냄

if ( FD_ISSET(c,&wk_set) ) {

if ( process_client(c) == EOF ) {

for ( c = mx - 1; c >= 0 && !FD_ISSET(c,&rx_set); c = mx - 1 ) mx = c;

Mx 값 줄여줌

Clr 된 만큼 줄여준다

Page 58: 11 장 동시 클라이언트 서버

58HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

18. 클라이언트 등록 위해 fd_set 사용 rx_set 집합등록 (282) FD_SET(c,&rx_set);

지금까지 서버 초기화와 새로운 클라이언트 연결을 받았다 .

이제 클라이언트가 자료를 보내고 서버가 처리하는 단계 를 살핀다 .

1. fd_isset 을 매크로를 불러서 소켓 s 에 입력 자료 테스트 (226) if ( FD_ISSET(s,&wk_set) ) {

Page 59: 11 장 동시 클라이언트 서버

59HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

2. For 루프를 모든 파일 기술자가 최대값 mx 보다 작 을 때 까지 반복 (288)

for ( c=0; c<mx; ++c ) {3. if ( c == s ) continue; /* Not s */4. fd_isset 매크로 호출 만약 소켓 c 가 읽기를

기다리는 자료를 가진다면 기술자 집합 wk_set 이 테스트

if ( FD_ISSET(c,&wk_set) ) {

Page 60: 11 장 동시 클라이언트 서버

60HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

5. 스텝 4 테스트값이 트루라면 소켓 c 와 함께 함수 process_client() 호출 (292)

if ( process_client(c) == EOF ) {

6. 테스트 값이 eof 라면 소켓 c 는 fd_clr 매크로를 사용하여 rx_set(293) 를 클리어 시킨다 .

FD_CLR(c,&rx_set);7. For 루프 실행 값 mx 보다 작은 일을 가능하다면 (301

~304) for ( c = mx - 1;

c >= 0 && !FD_ISSET(c,&rx_set); c = mx - 1 ) mx = c;

Page 61: 11 장 동시 클라이언트 서버

61HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버파일 구조 rx 설치 FILE *rx = client[c].rx;

rpn 스택 설치

stack = client[c].stack;

sp = client.sp;

!EOF & 처리 if ( !feof(rx) && fgets(buf,sizeof buf,rx) )

클라이언트 요청 실행rpn_process(tx,buf);

client[c].sp = sp; Save sp 저장

Page 62: 11 장 동시 클라이언트 서버

62HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

클라이언트 배열 초기화

return EOF;Eof 리턴

client[c].rx = client[c].tx = NULL;while ( sp > 0 )

rpn_free(&stack[--sp]); free(stack);

client[c].stack = NULL client[c].sp = 0;

fclose(tx);

shutdown(fileno(rx),SHUT_RDWR); fclose(rx); 입출력 스트림 닫고

읽기쓰기종료

Page 63: 11 장 동시 클라이언트 서버

63HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

함수 process_client 1. 지역변수 rx, tx 가 배열 client[c] 배열 멤버로부터

설치 FILE *rx = client[c].rx; FILE *tx = client[c].tx;

2. rpn 스택은 클라이언트에 외부 변수 stack 와 sp 로 된 client[c] 로부터 할당된 값으로 설치된다 .

stack = client[c].stack; sp = client[c].sp;

Page 64: 11 장 동시 클라이언트 서버

64HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

3. Eof 발견 테스트 (89) if ( !feof(rx) && fgets(buf,sizeof buf,rx) ) rpn_process(tx,buf);

5. rpn_process() 함수 호출해서 클라이언트 요청 실행

6. eof 테스트 (93) if ( !feof(rx) ) { client[c].sp = sp; /* Save SP and exit */ return 0;

Page 65: 11 장 동시 클라이언트 서버

65HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

7. 클라이언트가 쓰기를 하고 소켓을 끝내고 셧다운한다 (102)

* Close this client's connection: fclose(tx); shutdown(fileno(rx),SHUT_RDWR); fclose(rx);10. Client [] 배열 기입을 클리어 (106~113) client[c].rx = client[c].tx = NULL; while ( sp > 0 ) rpn_free(&stack[--sp]); free(stack); client[c].stack = NULL; client[c].sp = 0;

Page 66: 11 장 동시 클라이언트 서버

66HANNAM UNIVERSITYHttp://netwk.hannam.ac.kr

11.5 select(2) 11.5 select(2) 를 적용한 서버를 적용한 서버

11. eof 리턴 return EOF;