WSAAsyncSelect

2021. 11. 13. 00:29게임서버/namespace univ_dev

320x100

안녕하세요 대학생개발자입니다.

이번글에서는 AsyncSelect모델을 가지고 같이 그림을 그릴수 있는 보드를 만들어봤는데요...

우선 AsyncSelect가 뭔지 부터 간단히정리하고 가겠습니다.

 

AsyncSelect 말그대로 select를 비동기적으로 수행한다는겁니다.

select를 비동기적으로 한다는건 무슨의미일까요...

음... 일단 select를 다시한번 말씀드린다면... 게임에서의 select서버는 프레임에 맞춰서 루프를 계속 돌면서 폴링을 하는 방법이라고 정리를 했었습니다.

그럼 비동기 select니까 얘도 폴링을 하는 식으로 만들겠구나 라고 생각할 수 있는데요.

음... 사실 이부분에서 select와 async select모델은 전혀 다릅니다.

async select의 경우에는 폴링기법으로 로직을 루프하는 방법이 아니라 이벤트 드리븐 방식으로 이벤트가 나타나면 그 이벤트에 대한 처리를 하는 방식으로 설계가 되어있습니다.

즉 윈도우 메시지 기반이라는 의미입니다.

select의 기능을 내부에서 처리해주고 온게 있다면 그걸 이벤트로써 알려주고 그 뒤에 그거에 따른 로직이 도는겁니다.

사실 비동기select의 경우에는 예전에 클라이언트에서 많이 썼던 기법입니다.

물론 지금은 ms에서도 비권고하고있습니다. 이유는 나중에 설명드리겠습니다.

우선 장점에 대해서 좀 나열해보면

내부적으로 처리를 해주기 때문에 소켓에 갯수 제한이 걸리지 않습니다. 즉 select에서 하나의 set은 64개로 제한되어있지만 비동기select에서는 그렇지 않다는 의미죠.

추가로 불필요한 폴링작업이 생기지 않는다는 점입니다.

그에비해 단점이 너무나도 치명적인데요...

일단 우선 윈도우 메세지를 받아서 처리해야되다보니... 일단 윈도우 프로시저에 매우 종속적입니다.

추가로 싱글스레드만을 지원한다는건데요... 음 요새는 윈도우 운영체제 자체도 권장인지 기본인지 사양이 2코어로 깔려있습니다.

그렇기때문에 서버같이 아주 고성능이어야되고 아주 처리가 빨라야되는 상황이라면 별로 좋지않죠... 그리고 한번에 하나의 메세지만 도착하기때문에 하프 듀플렉스 구조입니다... 이게 무슨 비동기인데 동시에 안된다네요 ㅋㅋ.... 째뜬 이런 치명적인 단점이 존재하기 때문에 서버에서는 사용하지 않고있습니다.

 

뭐... 코드에서 약간의 이점이라고 하면 자동으로 논블러킹 소켓으로 전환된다 입니다. 당연히 윈도우 메시지를 기반으로 해야되기때문에 블로킹에 걸리면 안됩니다... 블로킹에 걸리게되면 윈도우 메세지를 처리하지 못하기때문에 응답없음이 뜰테니까요...

뭐... 이점에 비해 단점이 더많죠. 논블럭이기때문에 WSAEWOULDBLOCK체크는 피해갈수 없는거구요.

 

일단은 select 모델보다 더 좋아진 점은 더 많은 케이스가 존재합니다.

select의 경우에는 당연 read, write, exception 세가지의 경우밖에 확인할 수 없었지만... 비동기select의 경우에는 connect, read ,write , close, oob...등 좀더 많은 경우의 수가 있어서 쪼금더 편해진점이 있습니다.

 

일단 우선 메시지들에 대해서 좀 알아볼건데요.

read의 case가 나오는건... 말그대로 들어온게 있다면입니다. 그래서 L4버퍼에 데이터가 있다면... 내가 recv를 호출하기 전까지는 read가 튀어나오게 될겁니다. 말그대로 받을 게 있다에 대한 정보를 주는겁니다.

write의 case는 음... 보낼 게있다는 아니겠죠 보낼게있다는 L7에서 판단하는 영역이니까요 그럼 뭐에대한 내용일까요?

이건 보낼 수있다에 대한 정보를 알려주는겁니다. 근데 안타깝게도 이벤트 드리븐 형태의 단점이라고 해야될려나... 한번 온 메시지는 다시 오지 않습니다 왜냐면 직전의 상태와 지금의 상태를 비교해서 달라지면 시그널을 주는 형식이기 때문인데요... 그래서 write가 도착했다면 바로 뽑을수 있는만큼 전부다 뽑아버려야됩니다.

 

그럼 보낼 수 있는 상황은 어떤상황이란 걸까요?

음... 2개정도로 줄여볼수있는데요 1번은 내 송신버퍼가 가득차있다가 송신버퍼에 내용이 flush되면서 보낼수있게 되었다의 케이스가 있겠고요 두번째는 최초 연결되었을때입니다. 그럼 두개의 케이스일때 보낼 수 있으니까. 그때를 놓치게되면 내가 send를 따로 하지 않는이상은... write의 case는 나오지 않을겁니다.

 

이렇게 하는 이유는 select는 폴링이기 때문에 사용 가능한가 불가능한가에 대한 정보를 매 프레임마다 알수있지만... 이벤트 드리븐같은 경우에는 이번을 놓쳐버리면 그시그널이 오지 않기때문에 안타깝지만 한번에 보낼수있는건 모조리다 보내버려야된다가 되는겁니다.

 

일단 async select에서 주요한 함수는 WSAAsyncSelect함수겠는데요... 여기들어가는 파라미터들을 보면...

처음으로 윈도우의 핸들을 넣고 그 다음 튀어나올 메시지의 종류를 입력하고 다음으로 어떤 내용에 대한 이벤트인지를 비트플레그로 넣어주는겁니다. 뭐... 클라이언트의 경우에는 connect, read, write, close의 경우 정도 넣으면 되겠네요...

일단은 실행 사진을 먼저 올려놓고 다음번에 이어서 정리를 해야될 것 같아요 코드가 들어가면 내용이 갑자기 길어질 것 같은 불길한 얘감이 들거든요 ㅋㅋㅋㅋ....ㅠㅠ

음... 영상은 이렇게밖에 안올라가나보네요 ㅠㅠ 어떻게 올려야될지 모르겠어서 일단 유튜브를 올려야겠어요

https://youtu.be/bZMFaOSn3Zk

수정 : 죄송합니다 업로드할때는 몰랐는데 다른분이랑 모각코를 하면서 촬영했더니 그분 목소리가 들어갔네요...ㅋㅋㅋ

음성도 같이 녹음되는지 몰랐습니다 뭐 보시는데 크게 문제될 부분은 없으니까 대충 그러려니 하고 넘어가주시면 감사하겠습니다...

 

네 다행히 이런식으로 잘 작동하네요 ㅋㅋ... 예전에 만들었던거에서 네트워크만 넣은거라...

위에 rgb부분이 제대로 안찍혀있긴해요 그부분은 제가 영상을 찍고나서 알게되서... 나중에 고칠게요...

 

원래 게임서버라고하면 로직처리가 대부분인데...

아직까지 서버에서 로직을 처리할 부분이없어요 그래서 서버가 너무 간단하게 나오는데요...

뭐... 클라이언트가 끝나고 나면 일단 서버도 올리긴할게요... 근데 그냥 받은거 브로드캐스팅이 다라서 ㅋㅋㅋ...

큰의미없습니다.

 

그럼 오늘도 긴글 읽어주신 여러분들께 진심으로 감사드립니다.

다음번에는 이거 소스를 가져와서 정리를 마져해보려고합니다!!

그럼 안녕히계세요~

320x100