Non-Blocking Socket

Date:     Updated:

카테고리:

태그:

인프런에 있는 루키스님의 게임 서버 강의를 듣고 정리한 내용입니다.


Non-Blocking Socket

if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
    int32 errorCode = ::WSAGetLastError();
    cout << "Connect ErrorCode : " << errorCode << endl;
    return 0;
}

기본적으로 소켓은 Blocking 모드로 동작한다. 위 코드와 같은 소켓 작업(ex. connect, accept, bind, send, recv)은 완료될 때까지 해당 함수의 호출을 반환하지 않는다. 즉, sendBuffer가 가득 찾다거나 recvBuffer가 비어있을 경우 클라/서버는 프로그램이 일시적으로 중단(blocking)된다는 것이다. 패킷 전송이 매우 빈번할 경우 이는 매우 비효율적이다.

반면 Non-Blocking 모드의 경우 소켓 작업을 수행하는 함수가 즉시 반환하는 방식이다. 즉, 해당 작업이 당장 불가능하다면 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있다. Lock에서 마주친 상황과 매우 유사하다..


// Definition
int ioctlsocket(
  [in]      SOCKET s,
  [in]      long   cmd,
  [in, out] u_long *argp
);

// Set Non-Blocking Socket
u_long on = 1;
if (::ioctlsocket(listenSocket, FIONBIO, &on) == INVALID_SOCKET)
    return 0;


while (true)
{
    SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
    if (clientSocket == INVALID_SOCKET)
    {
        // 원래 블록했어야 했는데... 너가 논블로킹으로 하라며?
        if (::WSAGetLastError() == WSAEWOULDBLOCK)
            continue;

        // Error
        break;
    }
}

  • ioctlsocket(input/output control socket) 함수를 이용해 특정 소켓을 Non-Blocking 모드로 설정
  • FIONBIO : File Input/Output Non-Blocking Input/Output
  • WSAGetLastError == WSAEWOULDBLOCK (operation would block) : 지금 당장은 완료할 수 없음
  • 위 코드에서는 될때까지 while문 반복
  • spinLock 방식 말고도 여러 방법을 이용해 효율적으로 사용할 수 있음(이후 포스팅..)



맨 위로 이동하기

Server 카테고리 내 다른 글 보러가기

댓글 남기기