게임서버

게임서버) 7. 논블로킹 소켓

PJNull 2023. 1. 12.
728x90
반응형

논블로킹 소켓

 

소켓 관련 시스템 콜에 대하여 네트워크 시스템이 즉시 처리할 수 없는 경우라도 시스템콜이 바로 리턴되어 응용 프로그램이 block되지 않게 하는 소켓 모드이다. 싱글게임이 아닌 온라인 게임과 같이 통신 상대가 여럿이거나 여러가지 작업을 병행하려면 nonblocking 또는 비동기 모드를 사용해야 한다.

 

 

ioctlsocket function (winsock.h) - Win32 apps

The ioctlsocket function (winsock.h) controls the I/O mode of a socket.

learn.microsoft.com

 

서버 논블로킹 소켓 생성

 

논블로킹 소켓은 블로킹소켓을 생성했을때와 동일한 순서로 생성하되, 바인딩전에 아래와 같은 코드를 설정해주어야 한다.

u_long on = 1;
if (::ioctlsocket(listenSocket, FIONBIO, &on) == INVALID_SOCKET)return 0;

이후 블로킹소켓과 동일하게 바인딩과 Listen을 설정해준후 Accept를 설정해주어야 하는데, 여기서 블로킹과 차이가 발생한다.

	while (true)
	{
		SOCKADDR_IN ClientAddr;
		int32 addrLen = sizeof(ClientAddr);
		SOCKET clientSocket=::accept(listenSocket,(SOCKADDR*)&ClientAddr,&addrLen);
    	}

원래의 accpect함수는 연결이 될때까지 대기하는 함수이지만 논블로킹소켓에서는 연결이 되지 않더라도 대기를 하지 않게 되며 성공했을때와 실패했을때를 둘다 고려를 해야된다.

if (clientSocket == INVALID_SOCKET)
	{
	if (::WSAGetLastError() == WSAEWOULDBLOCK)continue;
	}

WSAEWOULDBLOCK은 에러상황이 아닌 블로킹이슈로 인해 에러가 났다는 것을 알려주는 것이다. 

Accept가 성공했다면 클라이언트와 통신을 할 차례이다. 하지만 여기서 또 문제점이 발생하는데, 하나는 앞서 설명한 블로킹이슈이며 나머지는 번호체크를 하여 판별하고 예외처리를 해주어야한다.

while (true)
	{
		char recvBuffer[100];
		int32 recvLen = ::recv(clientSocket,recvBuffer,sizeof(recvBuffer),0);
		if (recvLen == SOCKET_ERROR)
		{
			if (::WSAGetLastError() == WSAEWOULDBLOCK)continue;
		}
          	 if(기타에러들)break;
	}

 

클라이언트 논블로킹 생성

 

클라이언트 논블로킹도 서버 논블로킹에서 행했던 것과 비슷한 형식으로 생성할수 있다.

u_long on = 1;
	if (::ioctlsocket(ClientSocket, FIONBIO, &on) == INVALID_SOCKET)return 0;

 

그리고 Connect와 Send에서 에러를 체크해준다.Connect에서는 WSAEWOULDBLOCK와 WSAISCONN을 체크해주고Send에서는 WSAEWOULDBLOCK만 체크해주면된다. 여기서 WSAEISCONN는 이미 커넥션이 완료되었다는 것을 알려주는 코드이다.

	while (true)//Connect
	{
		if (::connect(ClientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
		{
			if (::WSAGetLastError() == WSAEWOULDBLOCK)continue;
			if (::WSAGetLastError() == WSAEISCONN)break;
		}
	}
    while (true)//Send
	{
    		char sendBuffer[100];
       	 	int32 sendLen=sizeof(sendBuffer);
      	  
		if (::send(ClientSocket,sendBuffer,sendLen,0) == SOCKET_ERROR)
		{
			if (::WSAGetLastError() == WSAEWOULDBLOCK)continue;
		}
	}

 

논블로킹의 문제점

 

논블로킹의 문제점은 위의 코드에서 알수 있듯이 수시로 에러가 있는지를 체크해야된다는 것이며, 불필요한 루프를 반복한다는 점에 있다.

728x90
반응형

'게임서버' 카테고리의 다른 글

게임서버) 11. IOCP Core  (0) 2023.01.17
게임서버) 8. Select모델  (0) 2023.01.13
게임서버) 6. 소켓프로그래밍  (0) 2023.01.11
게임서버) 3.멀티쓰레드 공유자원  (0) 2023.01.06
게임서버) 2. 멀티쓰레드  (0) 2023.01.06

댓글