Non-Blocking Socket
카테고리: Server
인프런에 있는 루키스님의 게임 서버 강의를 듣고 정리한 내용입니다.
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/OutputWSAGetLastError == WSAEWOULDBLOCK (operation would block)
: 지금 당장은 완료할 수 없음- 위 코드에서는 될때까지 while문 반복
- spinLock 방식 말고도 여러 방법을 이용해 효율적으로 사용할 수 있음(이후 포스팅..)
댓글 남기기