![]() |
![]() |
|||||||||||
[Schizo!, 2007. 9. 13. 18:57, study/programming]
다중 접속 서버 구현방법 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' 카테고리의 다른 글
|
||||||||||||
![]() |
![]() |
|||||||||||