select 함수의 기능과 호출 순서
- select 함수의 기능
- 배열에 저장된 다수의 파일 디스크립터를 대상으로 다음 과 같은 기능을 수행
1. 수신한 데이터를 지니고 있는 소켓의 존재여부 판단
2. 블로킹되지 않고 데이터의 전송기 가능한 소켓 판별
3. 예외 상황이 발생한 소켓 판별 - 호출 순서
- Step 1
- 관찰의 대상을 묶고, 관찰의 유형을 지정
▶ 핸들러 설정
▶ 검사의 범위 지정
▶ 타임아웃의 설정 - Step 2
- 관찰 대상의 변화를 물음
▶ select함수 호출 - Step 3
- 물음에 대한 답을 확인
▶ 호출 결과 확인
- Step 1
파일 디스크립터의 설정
- fd_set형 변수에 select 함수에 전달할 디스크립터의 정보를 확인
int main(void)
{
fd_set set;
FD_ZERO(&set) // 디스크립터를 모두 0으로 초기화
FD_SET(1,&set); // 디스크립터 1을 관찰 대상으로 추가
FD_SET(2,&set); // 디스크립터 2를 관찰 대상으로 추가
FD_CLR(2, &set); // 디스크립터 2를 관찰 대상에서 제외
}
- select 함수호출 이후에는 변화가 발생한(입력 받은 데이터가 존재하거나 출력이 가능한 상황 등), 소켓의 디스크립터만 1로 설정되어 있고, 나머지는 모두 0으로 초기화
select 함수
멀티플렉싱 서버 분석
fd_set reads, cpyReads;
....
{
FD_ZERO(&rerads); //select 함수의 관찰 대상이 되는 디스크립터들을 0으로 초기화
//hServSock은 리스닝 소켓이므로 연결요청이 오는지 확인하기 위해
FD_SET(hServSock, &reads) // hServSock을 관찰대상으로 등록
while(1)
{
// select 함수의 호출이 끝나면 변화가 발생한 디스크립터를 제외한 나머지는 0으로
// --> 즉, 삭제
// 그 전에 기존 디스크립터 정보들을 복사 하여 임시저장
cpyReads = reads;
timeout.tv_sec=t;
timeout.tv_usec=5000;
//select 함수 error c처리
//윈도우는 소켓정보가 다 날라가버림
if((fdNum=select(0, &cpyReads, 0, 0, &timeout)) == SOCKET_ERROR)
break;
//readset 즉 어떤 디스크립터(배열 내에) 에도 변화가 없음을 의미
//따라서 타임아웃 재설정 하고 재호출하기 위해 continue
if (fdNum==0)
continue;
}
}
- select 함수를 호출 -> 호출된 select 함수가 반환을 하면, 반환의 이유를 관찰하게 되지만, 타임아웃에 의한 반환이라면, 다시 select 함수를 호출하기 위해서 break 문을 실행해야한다.
// 파일 스크립터 내에 상태가 변경되었을 경우 (연결 요청 또는 데이터 수신)
// 상태가 변경되면 변경되지 않은 디스크립터는 삭제
for(i=0; i<reads, fd_count; i++)
{
// FD_ISSET 함수를 호출하여 변경된 cryReads 배열에 원소를 하나씩 비교하며 있는 확인
// 존재하면 변경되었다는 의미
if(reads.fd_array[i] == hServSock)
{
adrSz=sizeof(clntAdr);
hClntSock = accpt(hServSock, (SOCKADDR*)&clntAdr, &adrSz);
FD_SET(hClntSock, &reads); //관찰 대상 소켓으로 등록
printf("connected clinet : %d \n", hClntSock);
}
//hServScok가 아니라는 것은 데이터 수신을 의미
else
{
//데이터를 읽어 관찰대상에서 삭제하고 연결종료
strrLen = recv(reads.fd_array[i], buf, BUF_SIZE-1,0);
if(strLen == 0)
{
FD_CLR(reads.fd_array[i],buf,BUF_SIZE-1,0);
closesocket(cpyReads.fd_array[i]);
printf("closed client: %d \n",cpyReads.fd_array[i]);
}
}
}
- 연결요청과 알반적인 데이터 전송의 차이점
- 전송되는 데이터의 종류
- 연결요청도 데이터의 수신으로 구분이 되어서select함수의 호출결과를 통해서 확인이 가능
- 따라서 리스닝 소켓도 관찰 대상에 포함을 시켜야 한다.