ProudNet 사용과 관련해서 겪을 수 있는 문제 현상과 그것의 해결 방법을 소개합니다.
11.1디버거에 의해 일시정지하면 서버와의 연결이 끊어지는 문제 해결법
서버나 클라이언트를 디버깅하기 위해 디버거를 쓰던 중 디버깅 중인 프로그램이 중단점 설정 등에 의해 일시정지하기 마련입니다. 하지만 ProudNet을 쓰는 경우 이러한 일시정지 중 수십초가 지나면 서버와 클라이언트간의 연결이 끊어집니다.
ProudNet은 호스트간 연결이 비정상적으로 끊어지는 경우 대체적으로 즉시 감지합니다. 하지만 호스트의 전원이나 통신선을 강제로 뽑아버리는 등의 연결 해제(hard disconnect)를 하는 경우 즉시 감지하지 못합니다. 그리고 일정 시간마다 호스트간 주고 받는 핑퐁 패킷을 통해 hard disconnect 를 감지합니다. 디버깅 중인 프로그램이 수십초 동안 일시정지 상태인 경우도 ProudNet은 hard disconnect로 인식하여 호스트간의 연결을 해제합니다. 즉, 정상적인 상황이지만 아무래도 프로그램 개발을 하는 중에는 짜증날 수밖에 없습니다.
그림 11-1수십초 안에 버그의 원인을 잡고 일시정지를 풀어야 하다니! 우리가 지금 뇌수술중이냐!
이를 해결하기 위해서는 Proud.CNetServer.SetDefaultTimeoutTimeSec을 써서 hard disconnect를 감지하는 시간을 충분히 길게(예를 들어 한시간) 설정하면 됩니다.
주의 사항 : Proud.CNetServer.SetDefaultTimeoutTimeSec을 길게 설정하는 것은 디버깅 중일때만 권장합니다. 게이머에게 배포되는 버전에 Proud.CNetServer.SetDefaultTimeoutTimeSec를 길게 설정할 경우 hard disconnect를 하는 게이머의 연결 해제 감지를 감지하는데 너무 오랜 시간이 걸릴 수 있습니다. 간혹 hard disconnect를 악용하는 게이머들도 있을 수 있으므로 주의해 주시기 바랍니다.
사용예
Proud::CNetServer* srv = ...;
#ifdef _DEBUG
srv->SetDefaultTimeoutTimeSec(60*10); // 10분
#endif
11.2빌드 에러가 발생할 경우
#include <atlbase.h>를 include <ProudNetServer.h> or include <ProudNetClietn.h>를 하기 전에 해보시기 바랍니다. stdafx.h를 사용하는 경우 stdafx.h의 맨 앞단에 include <atlbase.h>를 넣는 것이 좋습니다.
.Net Framework를 사용하는 프로그램은 System.String이라는 심볼이 있습니다. 하지만 ProudNet은 Proud.String 이라는 심볼을 가지고 있습니다. 따라서 .Net Framework를 혼용하는 경우 String이라는 심볼은 System 혹은 Proud 중 하나의 네임스페이스를 명시해야 할 수도 있습니다.
11.3P2P 통신이 갑자기 안되다가 수초 뒤에 다시 통신이 재개되는 경우
ProudNet은 P2P 통신을 하던 중에 P2P 연결이 중간에 막혀버리면 그것을 감지하는데 수초의 시간이 걸립니다. 만약 P2P 연결이 중간에 막혔다는 것으로 판단되면 P2P 연결을 바이패스 모드로 전환합니다. 이때 주고받지 못했던 reliable 메시지들이 한꺼번에 주고받아지며 Unreliable Message들은 소실됩니다.
11.4P2P 통신이 잘 되다가 갑자기 안되는 경우
ProudNet은 기본적으로 P2P 통신이 어떤 형태로든지 될 수 있게 하는 데 목적이 있습니다. 만약 ProudNet에서 P2P 통신이 잘 안되는 경우는 전화나 인터넷으로 기술 지원을 문의해 주십시오.
만약 실 서비스 실행 중 이러한 문제가 발생할 경우 '안전 모드', 즉 UDP 통신을 모두 차단한 채로 임시로 서비스를 실행해야 할 수도 있습니다. 이를 위한 메서드는 Proud.CNetServer.SetDefaultFallbackMethod 입니다.
이렇게 하면 서버와의 통신에서 Unreliable Message도 TCP로 우회하며 P2P 통신은 항상 P2P relay가 될 것입니다. 이 또한 TCP로 주고받아지게 됩니다.
6.4 서버의 UDP 포트 사용 방식 도 참고하시기 바랍니다.
11.5Assert 대화 상자 막아버리기
ProudNet은 디버그 빌드에서 내부 작동 중 잘못된 사용이 있을 경우 assert failure 대화 상자를 표시할 수 있습니다. 이는 자연스러운 현상입니다.
그림 11-2Assert failure 대화 상자
만약 귀하께서 이를 막고 싶으시다면 assert failure가 발생할 때 대화 상자 표시 대신 다른 것이 작동하게 설정하셔야 합니다. 귀하가 만드는 함수로 대체도 가능합니다. 아래는 그 예입니다.
#include "stdafx.h" #include <crtdbg.h> int YourReportHook( int reportType, char *message, int *returnValue ) { return 1; } int _tmain(int argc, _TCHAR* argv[]) { _CrtSetReportHook(YourReportHook); assert(0); // now, this won't show you the message box. return 0; }
11.6CFastHeap 또는 CLookasideAllocator 관련 예외 발생시 해결 방법
Proud.CNetServer, Proud.CNetClient 를 포함해서 ProudNet의 많은 내부 객체들은 Fast Heap을 사용합니다. 그리고 Fast Heap
인스턴스를 C++ singleton 으로 둡니다. 이러한 특징 때문에 Fast Heap
을 사용하는 Proud.CNetServer, Proud.CNetClient 등의 인스턴스를 전역 변수 또는 전역 변수의 멤버 변수로 두면 예외가 발생하게 됩니다.
따라서 전역 변수로 두지 말고 C++ singleton 으로 두어야 합니다. C++ singleton
으로 만든 인스턴스는 WinMain() 혹은 main()이 리턴하기 전에 의존 객체 관계에 맞춰 파괴됨을 보장하기 때문입니다.
11.7RMI 메시지가 너무 짧아서 에러가 발생하는 경우
ProudNet의 RMI 메시지 크기는 제한이 설정되어 있습니다. 서버간 통신(10. 서버간 통신하기)이나 파일 전송이 필요한 환경에서는 이 상한선을 넘어가는 경우 에러가 발생합니다.
이 문제를 해결하려면 메시지 상한선을 조절해야 합니다. 자세한 것은 7. 통신 메시지의 크기 제한을 참고하십시오.
11.8최대 동시접속자 5000명을 넘기지 못하는 경우
최대 동시 접속자 5000명을 못 받는 경우가 있을 때에는, 다음을 확인해 보시기 바랍니다.
서버의 CPU 사용량이 지나치게 높은지?
서버의 메모리 사용량이 지나치게 높은지?
서버의 Non paged pool 사용량이 지나치게 높은지?
서버의 네트워크 통신량이 지나치게 높은지?
HKEY_LOCAL_MACHINE의 MaxUserPort(DWORD) 값이 5000 이하인지?
11.9ProudNetClientPlugin.dll 모듈을 찾을 수 없다고 나오는 경우
재배포 패키지가 설치되어 있지 않으면 해당 라이브러리가 경로에 존재하는데도 위의 오류가 발생할 수 있습니다. ProudNet 최초 설치시 마지막 단계에서 재배포 패키지와 CMake 를 설치하실 수 있습니다. 설치 후에는 ProudNet 설치경로 하위 Bin폴더에도 재배포 패키지가 들어있으니 해당 파일로 설치하셔도 됩니다.