글
■ 다중 입출력 서버를 구현하기 위해 select() 함수로 파일디스크립터의 변화를 확인.
(1) select() - 다중 입출력
: 여러개의 파일 디스크립터를 동시에 관찰하고, 변화가 있을 시 해당 파일 디스크립터를 반납한다.
○ 관찰항목
- 수신할 데이터를 지니고 있는 파일 디스크립터가 있는지.
- 데이터를 전송할 경우 blocking(무한대기) 상태가 되지 않고 바로 전달 가능한 파일 디스크립터가 있는지.
- 예외가 발생한 파일 디스크립터가 있는지.
=> 위와 같이 관찰 항목이 세가지이므로 파일 디스크립터들은 각 특성에 따라 readfds, writefds, exceptfds에 지정된다.
파일 디스크립터를 세 묶음으로 모아놓기 위해 하용되는 것이 fd_set 데이터 타입의 자료형이다.
fd_set은 0과 1로 저장하는 비트들의 배열이다.
○ 함수원형
int select((int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
- nfds : 검사 대상이 되는 fd 범위로 세개의 집합(readfds/writefds/exceptfds)중 가장 큰 파일 디스크립터 값에 1을 더해서 전달.
- readfds : 시스템에 의해 즉시 입력이 가능한지 확인(읽기가 block되지 않았는지 검사하기 위한 리스트/ EOF 발생 검사)
- writefds : 시스템에 의해 즉시 출력이 가능한지 확인(쓰기가 block되지 않았는지 검사하기 위한 리스트)
- exceptfds : 예외가 있는지 검사하기 위한 리스트
- timeout : select가 반환하기 전에 블럭킹될 수 있는 시간의 제한 값 (0은 즉시반환 / NULL은 무한 block)
○ 리턴값
-1 : 오류발생, 0 : 타임아웃, 0보다 큰수 : 변화 발생 파일 디스크립터 수
(2) FD_SET
: FD_SET 구조체 / 변수 조작하는데 사용되는 함수들
○ FD_SET 구조체
typedef struct fd_set { u_int fd_count; SOCKET fd_array[FD_SETSIZE]; } fd_set; |
- fd_count : 설정하는 파일 디스크립터의 번호
- fd_array : 설정된 파일 디스크립터의 배열
=> fd_set은 0과 1로 저장되는 비트들의 배열이다.
○ FD_SET 변수 조작 함수
- FD_SETFD_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로 전달되는 파일 디스크립터의 정보를 지니는지 확인
(3) timeout
: select 함수 호출 후 blocking(무한대기) 상태에 빠지지 않도록 timeout 을 설정하기 위한 인자 전달
○ timeout 구조체
struct timeval { long tv_sec; long tv_usec; } |
- tv_sec : 초 단위 설정 변수
- tv_usec : 마이크로 초 단위 설정 변수
(4) 결과확인
: FD_SET 변수에 변화가 생긴 파일 디스크립터는 1로 세팅, 변화가 없는 파일 디스크립터는 0으로 세팅한다.
- select 함수 호출 후 fd3만 1로 설정되어있다.
=> fd3에 변화가 생겼음을 확인 & 해당 파일 디스크립터와 데이터 통신을 진행한다.
(5) 다중 입출력 예제 소스
○ Source
○ Compile & Result
- FD_SET 으로 파일디스크립터 0번(표준입력) 설정
- 초기 표준입력이 없이 5초 후 타임아웃 발생 (select함수의 timeout인자 5초 설정)
- 파일디스크립터 0번(표준입력) 으로 welcome! 을 입력. (변화발생)
- fd_set 변수 reads에1 세팅.
- select 함수에서 변화확인하고, FD_ISSET으로 0번(표준입력)의 셋팅된 값 확인
- read 함수로 0번(표준입력)의 값 message에 저장
- message 값 출력
※ temp 변수의 사용
: 이미 준비해둔 fd_set 변수를 temp 변수에 복사해 두고 있다. 그 이유는 select 함수 호출이 끝나면 변화가 생긴 파일디스크립터 위치를 제외한 나머지 위치의 비트들이 0으로 초기화된다. 따라서 원본 변수를 직접 select 함수의 인자로 전달해 버리면 또 다시 변수를 설정하는 과정을 거쳐야 한다. 이를 막기 위해서 원본은 보존 하고 임시 변수에 원본을 복사해서 이것을 가지고 select 함수를 호출한다. 일반적인 select 함수 사용이니 반드시 기억해야한다.
'P rogramming > Socket' 카테고리의 다른 글
스트림 소켓(TCP)과 데이터그램 소켓(UDP) (0) | 2013.10.12 |
---|---|
리눅스 특정 포트 열기 / 닫기 (0) | 2013.10.12 |
UDP통신의 connect() 함수의 활용 (0) | 2012.03.08 |
TCP 소켓 프로그래밍 (Echo Client) (1) | 2012.03.06 |
TCP 소켓 프로그래밍 (Echo Server) (0) | 2012.03.06 |
RECENT COMMENT