본문 바로가기

CS/네트워크

[네트워크 개념 복습] Select 모델

개요

Select 모델은 구현이 간단하면서도 성능이 괜찮아 많은 곳에서 사용되고 있습니다.

또한 Windows, Linux에 모두 존재하기 때문에 포팅이 쉽습니다.

대표적으로 select모델은 unreal dedicated server에서도 사용됩니다.

https://basaeng.tistory.com/81

 

[네트워크 개념 복습] 소켓 알아보기

개요소켓은 L4계층의 데이터를 윗계층과 주고받을 수 있는 통로와 같습니다. L5부터는 커널이 아닌 유저모드의 영역이므로 이를 연결한다고도 볼 수 있습니다.https://basaeng.tistory.com/80 [네트워크

basaeng.tistory.com

이전의 포스팅을 확인하면 더 이해가 쉬울 것입니다.

 

select모델은 다중 소켓을 다루기위한 방식 중 하나입니다.


Select 모델 기본

select모델은 read set, write set, exception set을 사용해 소켓을 컨트롤 합니다.

 

readset: 읽어야할 데이터가 있는 소켓 목록을 넣습니다. recv가 필요한 소켓 + listen 소켓을 넣습니다.

writeset: 보내야할 데이터가 있는 소켓 목록을 넣습니다. send가 필요한 소켓을 넣습니다.

exceptionset: OOB혹은 예외 조건을 감지하는 소켓입니다.

 

int WSAAPI select(
  [in]      int           nfds,
  [in, out] fd_set        *readfds,
  [in, out] fd_set        *writefds,
  [in, out] fd_set        *exceptfds,
  [in]      const timeval *timeout
);

 

timeout은 select함수가 기다릴 시간입니다.

timeval구조체는 sec, microsec단위의 시간을 지정할 수 있습니다.

 

만약 이곳에 NULL을 넣는다면 set중에서 응답을 보이는 set이 하나도 없다면 반응하지 않습니다.

이 때는 해당 스레드가 blocking되기 때문에 CPU를 아끼는 효과를 볼 수도 있습니다.

 

만약 싱글스레드로 프로그램을 돌린다면 + select를 처리하는 로직 전반에서 다른 로직 처리가 필요할 수 있기 때문에 이 때는 적절한 시간을 기입하면 됩니다.

 

select를 호출하면에는 적절한 socket을 제외한 나머지 소켓을 set에서 제외합니다. 이후

FD_ISSET을 통해 특정 소켓이 set에 남아있는지 확인할 수 있습니다. (bool return)


Select모델의 흐름 

FD_ZERO를 통해 set초기화 -> FD_SET으로 알맞는 set에 socket들 삽입 -> select호출 -> FD_ISSET을 통해 socket이 처리가능한 데이터가 있는지 확인하고 이후 처리합니다.

 


FD 매크로

select 함수는 일반적으로 fd매크로를 활용해서 구현합니다.

fd매크로는 이름처럼 매크로이기 때문에 코드가 inline으로 바꿔쳐지는 구조입니다. 

 

FD_SET

Windows의 Select에서는 fd_set구조체를 통해 socket set을 담습니다. 

typedef struct fd_set {
        u_int fd_count;               /* how many are SET? */
        SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
} fd_set;

이를 위해 FD_SET매크로를 사용합니다.

 

FD_SET매크로에는 넣을 socket과 넣을 set을 지정합니다.

 

FD_ZERO

FD_ZERO매크로를 통해서는 set을 초기화합니다.

select를 호출하기 전 FD_ZERO를 호출해 set을 비워 한번의 루프마다 독립적인 연산이 가능하도록 합니다.

 

FD_ISSET

FD_ISSET매크로를 통해서는 select함수 호출 후에 socket이 set에 남아있는지를 확인합니다.

 

read set에는 recv했을 때 blocking되지 않는 경우 = L4에 socket이 받을 데이터가 있는 경우 = L4 수신 버퍼 데이터에 받을 수 있는 데이터가 하나라도 있는 경우

write set에는 send했을 때 blocking되지 않는 경우 =  L4에 socket이 데이터를 보낼 수 있는 경우 = L4 송신 버퍼가 꽉차지 않은경우

 

FD_CLR
개별 소켓을 set에서 제외할 수 있는 매크로입니다.


Select모델의 아쉬운 점

Select모델은 set당 최대 64개의 소켓만을 넣을 수 있습니다.(Windows) 따라서 더 많은 소켓을 다루기를 원한다면,  개수에 맞게 여러번 select를 호출해 여러번의 처리 로직을 거쳐야 합니다.

 

물론 어려운 작업은 아닙니다.