제 12장 I/O멀티플렉싱(Multiplexing) TCP/IP Socket Programming… 제 12장 I/O멀티플렉싱(Multiplexing) 시뮬레이션 실험실 박사 4학기 송수연
목차 멀티플렉싱 기반의 서버 Select 함수 사용하기 멀티플렉싱 서버의 구현 윈도우즈 기반으로 구현하기
I/O 멀티플렉싱 기반의 서버 멀티플렉싱? 데이터를 전송하는데 있어서, 물리적인 장치의 효율성을 높이기 위해 최소한의 물리적인 요소만 사용하여 최대한의 정보를 주고 받기 위해 개발된 방법 주파수 분할 방식 시 분할 방식
I/O 멀티플렉싱 기반의 서버 다중 접속 서버의 비교
Select 함수 사용하기 Select 함수의 기능과 호출 순서
Select 함수 사용하기 파일 디스크립터 설정하기 파일 디스크립터 범위설정하기 fd_set 자료형 데이터 조작함수 FD_ZERO(fd_set *fdset) ..*fdset의 모든 비트를 0으로. FD_SET(int fd, fd_set *fdset) ... *fdset 중 소켓 fd에 해당하는 비트를 1로. FD_CLR(int fd, fd_set *fdset) ... *fdset 중 소켓 fd에 해당하는 비트를 0으로. FD_ISSET(int fd, fd_set *fdset) ... *fdset 중 소켓 fd에 해당하는 비트가 1이고, 소켓에 I/O 변화가 생겼으면 true를 리턴 파일 디스크립터 범위설정하기 효율적인 슈행을 위해 확인해야하는파일 디스크립터의 범위를 제한해준다.
Select 함수 사용하기 타임 아웃(time out) 설정하기 timeout은 select() 호출할 때 얼마만큼(마이크로 단위)의 시간을 기다릴 것인지를 지정하는데 사용된다. timeout 구조체는 구조체 struct timeval의 자료형이며 에 다음과 같이 정의 되어 있다. ----------------------------------------------------------------------------------------- struct timeval { long tv_sec ; /* seconds */ long tv_user ; /* microseconds */ } -------------------------------------------------------------------------------------------
Select 함수 사용하기 SELECT 함수 호출 이후 결과 확인
Select 함수 사용하기 SELECT 함수 호출 예제 timeout.tv_usec = 100000; #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/time.h> #define BUFSIZE 30 Int main(int argc, char **argv) { fd_set reads, temps; int result; char message[ BUFSIZE ] int str_len; struct timeval timeout ; FD_ZERO(&reads); FD_SET(0, &reads); /* standard input 설정 /* timeout.tv_sec = 5; timeout.tv_usec = 100000; */ /* 이곳이 설정할 경우 문제 발생*/ while(1) { temps=reads; timeout.tv_sec=5; timeout.tv_usec=0; resullt=select(1, &temps, 0,0, &timeout); if(result==-1){ /*select 함수 오류 발생 */ puts(“select 오류 발생”); exit(1); } else if (result==0){ /* time-out에 의한 리턴 */ puts(“시간이 초과되었습니다 : select “); else { /* 파일 디스크립터 변화에 의한 리턴 */ if(FD_ISSET(0, &temps)) { str_len =read(0, message, BUFSIZE); message[str_len}=0; fputs(message, stdout); } /*while(1) end * /
Select 함수 사용하기 실행하기
멀티플렉싱 서버의 구현 echo_selserv.c if(fd_max<clnt_sock) fd_max=clnt_sock; printf( “ 클라이언트 연결 : 파일 디스크립터 &d \n”, clnt_sock); } else { str_len=read(fd, message, BUFSIZE); if(str_len==0){ /* 연결 종료 요청인 경우 */ FD_CLR(fd, &reads); close(fd); printf(“클라이언트 종료 : 파일 디스크립터 &d|n”, fd); else { write(fd, message, str_len); } //if (FD_ISSET(fd, &temps)) } //for (fd=0; fd<fd_max+1; fd++) } //while(1) Void error_handling(char *message) { fputs(message, stderr); fputc( ‘\n’, stderr0; exit(1); echo_selserv.c while(1) { int fd, str_len; int clnt_sock, clnt_addr temps=reads; timeout.tv_sec=5; timeout.tv_usec=0; if(select(fd_max+1,&temps, 0, 0, &timeout)==-1) error_handling( “select() error”); for(fd=0; fd<fd_max+1; fd++) if(FD_ISSET(fd, &temps)) if(fd==serv_sock) {/* 연결요청인 경우 */ clnt_len=sizeof(clnt_addr); clnt_sock=accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_ len); FD_SET(clnt_sock, &reaks);
멀티플렉싱 서버의 구현 실행 echo_selserv.c 실행하기 에코 클라이언트 실행하기
윈도우즈 기반으로 구현하기 SELECT함수의 원형 Timeout구조체 ----------------------------------------------------------------------------------------- struct timeval { long tv_sec ; // seconds long tv_user ; // and microseconds }; -------------------------------------------------------------------------------------------
윈도우 기반으로 구현하기 If(listen(hServsock, 5)==SOCKET_ERROR) ErrorHandling(“listen() error”); FD_ZERO(&reads); FD_SET(hServSock, &reads); While(1) { temps=reads; timeout.tv_sec=5; timeout.usec = 0; if(select(0, &temps, 0, 0, &timeout)==SOCKET_ERROR) ErrorHandlling(“select() error”); for(arrIndex=0; arrIndex<reads.fd_count; arrIndex++) if(FD_ISSET(reads.fd_array[arrIndex], &temps)) if(temps.fd_array[arrIndex]==hServSock) // 연결요청일경우. clntLen = sizeof (clntAddr); hClntSock = accept(hServSock, (SOCKADDR*)&clntaddr, &clntLen); FD_SET(hClntSock, &reads) ; printf( “클라이언트 연결:소켓핸들 %d \n”, hClntSock); } else //전된 데이터 존재하는경우.종료요청 혹은 데이터수신. straLen = recv(temps.fd_array[arrIndex], message, BUFSIZE-1, 0) ; if (strLen ==0) // 종료 요처의 경우. { FD_CLR(temps.fd_array[arrIndex], &reads); closesocket(temps.fd_array[arrIndex]); printf(“ 클라이언트 종료 : 소켓 핸들 %d\n” , temps.fd_array[arrIndex]); } else // 데이터 수신의 경우. send(temps.fd_array[arrIndex], message, strLen, 0); } //if(FD_ISSET(reads.fd_array(arrIndex], &temps)) end } //for(arrIndex=0; arrIndex<reads.fd_count; arrIndex++) end } //while(1) end WSACleanup(); return 0; Void ErrorHandling(chaar *message) { fputs(message, stderr); fputc( ‘\n’ , stderr) ; exit(1);
참고문헌 “UNIX Network Programming”, W.Richard Stevens “TCP/IP 소켓 프로그래밍”, 윤성우 저
Q & A