IOCP를 이용한 서버 만들기 이미 IOCP가 많이 알려진 상태이지만, 확장하기 쉽고 범용성있는 서버를 만들어 보고자, 정리차원에서 글을 써본다. 그리고 밑에 참고사이트와 자료를 링크해 놓고 각각의 소스를 비교해 보았으니 참조하기 바란다. I/O Completion Port ? IOCP가 무엇인지 더욱 완벽한 설명을 원한다면, Programming Server-Side Applications for Microsoft Windows 2000이란 책을 추천한다. 그 책에서 자세히 설명되어 있다. IOCP는 멀티프로세서 환경을 위해 특별히 설계된 윈도우 파일 입출력 모델중의 하나이다. 그래서 IOCP는 윈도우즈 NT계열(NT, 2000이상)에서만 유용하다는 점을 인식하고 있기 바란다. ##########0* 개념적으로 일단 IOCP 프로그래밍을 설명한다면 그림에서와 같이 APP(프로그램)가 IOCP로 행할 포트 를 정의한 뒤,(CreateIoCompletionPort함수이용) 그 포트로 I/O (뭔가를 쓴다던지 읽는다던지)하면 그 I/O가 끝날 때까지 프로그램은 기다릴 필요가 없이 리턴되고 OS가 직접 그 I/O를 행하여서 그것이 완료 되면 그 결과값을 가지고 있다가 프로그램이 그 결과값을 물어 볼 때(GetQueuedCompletionStatus or Callback 함수이용) 알려주고 프로그램은 그에 맞은 액션을 취하면 되는 것이다. 왜 이것을 IOCP(I/O 완료 포트 : Input/Output Completion Port)라고 부르는지 이해가 됐는가? IOCP 소켓 프로그래밍 위에서 간단하게 개념적인 것을 설명했지만, 본격적으로 이것을 응용한 윈도우즈 소켓 프로그래밍에 대해서 알아보자. 윈도우에서는 소켓을 화일과 마찬가지로 보기 때문에 소켓 프로그래밍에 IOCP를 사용할 수 있다. 물론 윈도우즈 소켓 프로그래밍에는 IOCP방식이외에 여러가지 방식이 있지만, 서버와 같은 대규모 유저가 접속할 가능성이 있는 프로그램을 작성할 때에는 IOCP방식을 사용해서 프로그래밍하는 것이 좋다고 한다. MS에서... 먼저 간단하게 IOCP 소켓 프로그래밍 구조를 디자인해 보자. 1. 새로운 IOCP용 포트를 생성한다. (CreateIoCompletionPort함수이용) 아래의 참고 소스들을 보면 알겠지만은 구조는 사용 용도에 따라 세부적인 부분이라든지, 순서가 조금씩 달라지게 된다. 하지만 전체적인 관점에서 보게 된다면 서로가 위와 같은 비슷한 구조를 취하고 있다는 것을 알게 될 것이다. 이제 위와 같은 구조를 바탕으로 확장하기 쉬운 범용성있는 서버를 한번 디자인해보자. 서버 제작 여기서 제작하고자 하는 서버 프로그램은 아래의 참고 소스들에서 조금씩 참조되였다. 그리고 서버를 ZenServer 라고 명명지였다. (참고로 Zen은 도사라는 의미로 사용되기도 한다고 한다. ^^;) ZenServer (ver 0.2)의 특징은 다음과 같다. 1. IOCP, 쓰레드, 이벤트를 사용한다. 우선 초기버전이므로 서버의 골격만 잡아 놓았다고 해도 과언이 아니다. 하지만 확장성이 준비되어 있는 만큼 다음 버전에서는 1. 로비(= 채널 or 방) 이동, 로비 생성 등이 가능할 것이다. (기능들은 다 준비되었지만, 코딩할 시간이 없어서.. 이번 버전에서는 제외된다.) ZenServer의 구조 디자인은 다음과 같다.
클라이언트 클래스 (CClient) CNetPrtc 서버 프로그램에서 접속해오는 사용자를 관리하는 일을 하는 클라이언트 클래스 CClient는 위와 같이 상속되어진 클래스이다. 왜 이렇게 많이 상속받는냐고 물어본다면 확장성때문이라고 필자는 이야기하고 싶다. 그럼 차근 차근 각클래스들이 어떤 할 일(역할이라는 말이 일본식 한자말이라 하더군요. ㅡㅡ;)을 하는지 보도록 하자. CNetPrtc는 가장 기본이 되는 네트워크 클래스로 모든 네트워크 통신 클래스의 공통사항이 담겨져 있다. 그래서 멤버에는 기본적인 소켓데이타밖에 존재하지 않는다. 이것을 상속받아 IPX나 TCP/IP, IOCP클래스들이 만들어 진다. (먼 미래를 바라보는 포석이라고 할까? ^^;) ID (데이타를 정의하는 ID로 16진수형 두바이트) + 데이타 지금 현재 정의된 것은 A0 (채팅데이타 명령) 밖에는 없지만, 나중에 추가될 예정이다.(사용할 수 있는 명령은 현재 00 ~ FF까지이다) 어쨌든 CClientIOCPEx에서는 전송받은 데이타를 분석하여 명령을 추출한 뒤 해당 함수, 즉 명령이 A0이라면 CClientIOCPEx에 있는 On0xA0함수를 직접 호출하여 준다. 또한 이러한 명령관련 함수가 모두 가상함수로 선언되어 있기 때문에 CClientIOCPEx를 상속하면 해당명령관련 함수만 재정의하여 사용하면 되므로 필자는 이를 상속한 CClient라는 클래스를 만들게 되었다. 이제까지 장황하게 설명을 했는데, 잘 이해가 되었는지 모르겠다. 여러분이 소스를 보면 더 이해가 잘 갈지는 모르겠지만, 여기서 설명한 내용이 거의 주가 되므로 잘 이해하기 바란다. 테스트용 클라이언트 프로그램은 전에 필요에 따라 만들었던 것을 조금 개조하여 사용했다. 클라이언트 프로그램소스에서는 위의 CNetPrtc를 계승한 CTcpPrtc이 있으므로 참조해 보기 바란다. 그럼 다음 버전의 ZenServer를 기약하면서...
참고 자료 : 1. 프로그램세계 (2002/03 노규남 - 윈도우용 IOCP 채팅서버 만들기) : 가장 간단한 구조의 서버 소스이다. 그래서 IOCP의 기초를 파악하는데 가장 쉬운 편이지만, 소스를 활용할 수는 없는 편이다. 2. Multithreading Applications in Win32 (서적) : 그 다음으로 간단한 구조의 에코서버 소스이다. 위보다는 조금 더 실용적이라고 할 수 있다. 2. CodeProject (Writing scalable server applications using IOCP) : 실용적으로 IOCP 서버를 구성하기할 때 필요한 요소를 작성하였다. 다만, 소스만 나열되어 있어 사용자가 프로젝트를 생성해서 야 된다. 3. MVPS (Sockets, IOCPs, AcceptEx) : 2번 서버소스와 구조와 비슷하다. 소스를 조금만 다듬는 다면 활용할 수 있는 수준이다. 4. MSDN (Writing Scalable Application for Windows NT) : 조금 다른 구조로 서버를 구성하고 있는 소스이다. MSDN에서 나온 소스인 만큼 참조해야 할 소스이다. 5. 임창하 (IOCP - W2K용 서버와 NT용 서버) : 구조를 객체 지향적으로 만들려고 노력한 소스이다. 그래서 IOCP를 이해하는데에는 다소 좋지 않지만(?) 소스의 활용도는 높은 편이다. 그리고 W2K전용과 NT이상용을 구분하여 작성한 점이 눈에 띈다. |
'Development > 네트워크 프로그래밍' 카테고리의 다른 글
패킷 압축 방법 (0) | 2011.08.13 |
---|---|
서브넷 계산 및 표현법, 192.168.0.0/32, CIDR (0) | 2011.08.13 |
[펌] IOCP를 이용한 서버 만들기(소스) (0) | 2011.08.13 |
[펌] 펌) IOCP - 윈속 프로그래밍 (0) | 2011.08.13 |
[펌] [Socket] 소리바다 TCP/IP 프로그래밍 개념 요약1 (0) | 2011.08.13 |