관리 메뉴

알고리즘

tcp/ip 본문

study/programming

tcp/ip

Schizo! 2007. 9. 13. 18:57

다중 접속 서버 구현방법

1. 프로세스 생성을 통한 멀티태스킹서버

2. SELECT함수에 의한 멀티플렉싱 서버

3. 쓰레드를 기반으로 하는 멀티쓰레딩 서버


1번방법은 10장 11장에서 보았다.

1번요약 :
fork() 로 프로세스 생성
sigaction()으로 자식프로세스 종료 확인
pipe()로 프로세스간 통신

12장은 2번방법.


1번과 2번 방법의 차이는 다음과 같다.


 
 
 
서버는 주기적으로 데이터를 전송해오는 클라이언트가 있는지 확인을 하다가, 발견한 경우, 그 클라이언트로부터 데이터를 수신한다
 
이를위해 select함수가 사용된다.
 
int select(검사대상갯수,수신검사소켓,송신검사소켓,예외,타임아웃);
-검사대상갯수는 윈도우에선 의미없음.
-select함수 호출후 변화가 생긴 소켓을 제외하고 모두 0으로 초기화된다.(따라서 0이 아닌소켓이 변화가 생긴 소켓)
-select함수 호출후 시간은 타임아웃은 타임아웃까지 남은시간으로 재설정된다.
-리턴값 : 0 : 타임아웃 , -1 : 오류 , 0보다큰값 : 변화가 있는 소켓수.
 
함께쓰이는 함수
FD_ZERO(fd_set* fdset)
FD_SET(int fd, fd_set* fdset)
FD_ISSET(int fd, fd_set* fdset)
 
 
예:
 
//두개의 소켓이 있다고 가정.
hServerSocket = socket(PF_INET,SOCK_STREAM,0);
 
hClntSocket = accept(hServerSocket,(SOCKADDR*)&clntAddr,&clntLen);
 
//변수선언
fd_set reads,temps;
 
FD_ZERO(&reads);                     //reads변수 초기화
FD_SET(hServerSocket,&reads);  //hServerSock에 변화가 있는지 관찰하겠다.
 
 
while(1)
{
                temps = reads;            //select호출후 0으로 초기화 되므로 이렇게 해주어야 한다.
                timeout.tv_sec = 5;     //select호출후 남은시간으로 변경되므로 이렇게 해주어야 한다.
                timeout.tv_usec = 0;;
 
                select(0,&temps,0,0,&timeout);    //temps에 수신데이타가 있는지 관찰하겠다.
 
                if(FD_ISSET(hServerSock,&temps))
                {
                          //hServerSock에 연결요청이 들어왔다
                }
                else
                {
                        //아닌경우 처리......
                }
}
 
 
 
 
요약 :
FD_SET으로 관찰할 소켓을 지정한 다음
select()로 지정한 소켓들을 관찰하고
FD_ISSET으로 관찰하는 소켓에 변화가 있는지 확인한다.
 
 
활용 :
에코서버를 수정하여 여러개의 클라이언트가 접속할수 있도록 처리할 수 있다.
1. 클라이언트가 접속할때마다  fd_set에 추가
2. 클라이언트가 접속을 끊을때마다 fd_set에서 삭제
2. select로 체크한후
3. 변화가 생긴 소켓에 에코한다.
 
 
hServSock = socket(PF_INET,SOCK_STREAM,0);
 

//fd_set설정

FD_ZERO(&reads);

FD_SET(hServSock,&reads);

 

while(1)

{

             temps = reads;          //select호출후 0으로 초기화 되므로 이렇게 해주어야 한다.

             timeout.tv_sec = 5;   //select호출후 남은시간으로 변경되므로 이렇게 해주어야 한다.

             timeout.tv_usec = 0;

            

             if( select(0,&temps,0,0,&timeout)==SOCKET_ERROR )      //temps에 수신데이타가 있는지 관찰하겠다.

                           ErrorHandling("select() error");

            

             for(arrIndex=0;arrIndex<reads.fd_count;arrIndex++)        //reads.fd_count는 계속 바뀔것이다.

             {                                                                                     

                           if(FD_ISSET(reads.fd_array[arrIndex],&temps))         //변화가 생긴 소켓이 있는가.

                           {

                                        if(reads.fd_array[arrIndex]==hServSock)     //변화가 생긴 소켓이 연결요청인경우

                                        {

                                                     clntLen = sizeof(clntAddr);

                                                     hClntSock = accept(hServSock,(SOCKADDR*)&clntAddr,&clntLen);

 

                                                     FD_SET(hClntSock,&reads);               //연결요청을 받아들이고 fd_set에 추가

                                                     printf("클라이언트 연결 : 소켓핸들 : %d \n",hClntSock);

                                        }

                                        else

                                        {

                                                     strLen = recv(reads.fd_array[arrIndex],message,1024,0);

 

                                                     if(strLen==0)

                                                     {

                                                                  closesocket(temps.fd_array[arrIndex]);

                                                                  printf("클라이언트 종료 : 소켓핸들 : %d\n",reads.fd_array[arrIndex]);

                                                                  FD_CLR(reads.fd_array[arrIndex],&reads);    //연결종료이면 fd_set에서 삭제

                                                     }

                                                     else

                                                     {

                                                                  send(reads.fd_array[arrIndex],message,strLen,0);

                                                     }

                                        }

                           }

             }

 

}

'study > programming' 카테고리의 다른 글

c  (0) 2007.11.12
07.11.04 정보처리산업기사 합격수기  (0) 2007.11.11
c  (0) 2007.11.10
반복문 9월 17일  (0) 2007.09.17
dd  (0) 2007.09.13
Comments