select()는 리눅스 / 유닉스 시스템에서 여러 파일 디스크립터를 동시에 감시하여, 읽기/쓰기/예외 이벤트가 발생한 파일 디스크립터를 감지할 수 있게 해주는 함수다.
- 여러 클라이언트의 요청을 동시에 처리할 수 있게 해준다.
- 여러 소켓을 동시에 감시할 수 있게 해준다.
- 단일 스레드 기반의 네트워크 서버에서 효율적으로 동시성 처리가 가능하다.
- 하지만 최대로 감지할 수 있는 클라의 수가 윈도우는 64개, 리눅스는 1024개 이기 때문에 제한이 있다.
✅ 예제
UINT nCount
FD_SET fdRead;
std::list<SOCKET>::iterator it;
// 클라 접속 및 정보 수신 변화 감시셋을 초기화 한다.
FD_ZERO(&fdRead);
for(it = g_listClient.begin(); it != g_listClient.end(); ++it)
{
FD_SET(*it, &fdRead);
}
// 변화가 발생할 때까지 대기한다.
::select(0, &fdRead, NULL, NULL, NULL);
// 변화가 감지된 소켓을 확인한다.
nCount = fdRead.fd_count;
for(int nIndex = 0; nIndex < nCount; ++nIndex)
{
// 소켓에 변화 감시 플래그가 설정 되었는지 확인한다.
if(!FD_ISSET(fdRead.fd_array[nIndex], &fdRead))
{
continue;
}
// 감지된 소켓이 listen 소켓인지 확인한다.
// 다시 말해, 클라가 연결을 시도했는지 여부를 확인한다.
if(fdRead.fd_array[nIndex] == g_hSocket)
{
// 새 클라이언트의 접속을 받는다.
SOCKADDR_IN clientaddr = { 0 };
int nAddrLen = sizeof(clientaddr);
SOCKET hClient = ::accept(g_hSocket, (SOCKADDR*)&clientaddr, &nAddrLen);
if(hClient != INVALID_SOCKET)
{
FD_SET(hClient, &fdRead);
g_listClient.push_back(hClient);
}
}
else // 클라이언트가 전송한 데이터가 있을 경우
{
char szBuffer[1024] = { 0 };
int nReceive = ::recv(fdRead.fd_array[nIndex], (char*)szBuffer, sizeof(szBuffer), 0);
}
}
'네트워크' 카테고리의 다른 글
[네트워크] I / O 멀티플렉싱 (0) | 2025.04.17 |
---|---|
[네트워크] 우아하지 않은 비정상 종료 (0) | 2025.04.14 |
[네트워크] 멀티 쓰레드 채팅 클라이언트 (0) | 2025.04.14 |
[네트워크] 멀티쓰레드 채팅 서버 (0) | 2025.04.13 |
[네트워크] 멀티 쓰레드 Echo (0) | 2025.04.11 |