멀티플렉싱 서버의 구현에 있어서 가장 대표적인 방법 : select()
select함수를 사용하면 한곳에 여러 개의 file descriptor를 모아놓고 동시에 이들을 관찰할 수 있다.
*파일 디스크립터의 관찰은 소켓의 관찰로 해석할 수 있다.
파일 디스크립터에 대한 관찰을 하는 데 사용되는 것이 fd_set형 변수이다. 이는 0과 1로 표현되는, 비트단위로 이뤄진 배열이다.
이러한 자료형으로 각 file descriptor에 대해 세 가지에 대해서 관찰을 한다.
- read buffer 관련
- write buffer 관련
- exception 관련
이러한 관찰범위를 select 함수에 fd_set 변수를 선언하여 변수의 주소값을 넘겨준다.
관심없는 관찰에 대해선 NULL을 넘겨주면된다.
select의 parameter를 살펴보면 다음과 같다.
readfds 는 read buffer 즉, '수신된 데이터의 존재여부'에 관심 있는 file descriptor 정보를 모두 등록해서 그 변수의 주소 값을 전달한다.
writefds 는 write buffer 즉, '블로킹 없는 데이터 전송의 가능여부'에 관심 있는 file descriptor 정보를 모두 등록해서 그 변수의 주소 값을 전달한다.
exceptfds는 exception 즉, ' 예외상황의 발생여부'에 관심있는 파일 디스크립터 정보를 모두 등록해서 그 변수의 주소 값을 전달한다.
※readfds, writefds, exceptfds는 모두 서로 다른 fd_set 형 변수이다.
관찰 대상이되는 파일 디스크립터의 수를 나타내는 nfds에 대해서 알아보자.
여기서 주의해야할 것은 관찰 대상이 되는 file descriptor의 정확한 개수를 넘기는 게 아니라
'가장 큰 file descriptor의 값 + 1' 을 select의 가장 첫번째 인수로 넘겨준다는 것이다.
이 의미는 fd_set형 배열을 nfds만큼 순회하면서 값이 1인 file descriptor를 캐치한다는 것이다.
Q. 관찰을 원하지 않는 file descriptor의 변화를 감지할 수 있지 않은가?
우리는 fd_set형 변수에서 관심있는 file descriptor를 1로 set한다. 그리고 이 fd_set 변수는 초기화하는 데 사용되고
이 변수를 또다른 fd_set형 변수를 선언하여 복사해준다.
그래서 매번 select 하기 전에 원래의 fd_set(1)으로 초기화한다. 그 다음, select의 fd_set 자리에는 복사한 fd_set(2)형 변수의 주소값을 넘겨준다.
select는 fd_set의 1로 셋팅된 것으로 관찰 대상인 file descriptor를 판별하는데 매번 초기화를 안 해주면 들어갈 때마다 값이 바뀌기 때문에 관찰대상이 계속 바뀌어 의미가 없어진다.
Select함수는 변화를 감지하기 위한 목적이 있다. 그래서 세 가지 관찰범위에 대해서 변화가 일어나지 않으면 반환을 하지 않는다. 이러한 infinite blocking 상태에 빠지지 않게 하기 위해서 설정한 timeout 시간을 초과하면 0을 반환하도록 한다.
실패하면 -1을 반환하고 성공 시, 변화가 일어난 file descriptor의 수를 반환한다.
'CS & IT실무' 카테고리의 다른 글
Half-Close - shutdown() (0) | 2018.10.05 |
---|---|
네트워크 바이트 순서와 인터넷 주소 변환 (0) | 2018.10.04 |
소켓에 할당되는 IP주소와 PORT번호 (0) | 2018.10.04 |