블로그 이미지
fiadot_old

칼퇴근을 위한 게임 서버 개발 방법론에 대한 심도있는 고찰 및 성찰을 위한 블로그!

Rss feed Tistory
Technical Article 2009. 2. 13. 20:49

Boost 1.38.0 Test만 빌드하는 방법

UnitTest를 위한 프레임웍을 살펴보던중 UnitTest++과 Boost::Test가 가장 눈에 띄었다.

UnitTest++ 다운 후 간단히 빌드가 되지만 Boost::Test를 사용하기 위해서는 몇가지 빌드 과정이 필요하다.

<준비>
XP+sp3, VS2005, boost 1.38.0

1. http://www.boost.org/ 에서 download로 가서 boost_1_38_0 파일을 다운로드

2. 압축을 풀고 tools/jam/src에서 build.bat 실행
   혹시 에러가 발생한다면
   (1) Path가 너무 많을때
   (2) 시작-프로그램-Microsoft Visual Studio 2005-Visual Studio Tools-Visual Studio 2005 명령프롬프트를 실행해서 해당 경로로 이동해서 실행

3. 해당 경로 밑에 bin.ntx86/bjam.exe가 생성됨.

D:\boost_1_38_0\tools\jam\src\bin.ntx86>set path=%path%;D:\boost_1_38_0\tools\jam\src\bin.ntx86

4. bjam으로 test release/debug 모두 빌드
D:\boost_1_38_0\libs\test\build>bjam -sBUILD=boost_unit_test_framework --toolset=msvc --build-type=complete

  인자 : 빌드옵션(release +  debug = complete)


시간 무지하게 걸린다 ㅡㅡ;;
,
Technical Article 2009. 2. 10. 16:27

Visual Studio 2005 단축키 설정이 제대로 바인딩 안될때 해결방법

Visual Studio 2005에서 도구-설정 가져오기 및 내보내기를 통해서 사용자가 지정한 단축키를 내보내기를 하고 재설치를 하거나 다른 컴퓨터에서 가져오기를 했을때 키보드 바인딩이 제대로 안되는 경험을 해보았을 것이다.

내보내기(export)한 파일(.vssettings)를 보게되면 지정된 단축키와 제거된 단축키와 관련된 전체 히스토리까지 저장되서 가져오기를 했을때 제대로 처리가 안된것이다.


1. 이를 방지하기 위해서 키보드 바인딩만 내보내기를 한다.

사용자 삽입 이미지

2. 저장된 파일을 텍스트 에디터를 이용해 Shortcut Command만 남기고 모두 삭제한다. 중복된 부분도 보이는데 이런 부분은 현재 사용중인것만 남기고 삭제한다.

3. 그리고 단축키를 제외한 파일을 만들어서 단축키와 환경설정에 대해서 별도로 관리를 하면 된다.
LEEGUNHO_VS2005_Keybinding.vssettings
LEEGUNHO_VS2005_WithoutKeyBinding.vssettings


■ 지정 단축키 ■

[code]
    <UserShortcuts>
     <Shortcut Command="VisualAssistX.SurroundSelectionWithComment" Scope="전역">Ctrl+/</Shortcut>
     <Shortcut Command="VisualAssistX.ReparseCurrentFile" Scope="전역">Ctrl+Shift+W</Shortcut>
     <Shortcut Command="Project.SetasStartUpProject" Scope="전역">Ctrl+Shift+'</Shortcut>
     <Shortcut Command="Window.CloseAllDocuments" Scope="전역">Ctrl+Shift+C</Shortcut>  
                   <Shortcut Command="Build.BuildSelection" Scope="전역">F7</Shortcut>
     <Shortcut Command="Build.RebuildSelection" Scope="전역">Ctrl+Shift+A</Shortcut>    
     <Shortcut Command="Project.AddNewItem" Scope="전역">Ctrl+Shift+N</Shortcut>
     <Shortcut Command="Project.AddClass" Scope="전역">Ctrl+Shift+M</Shortcut>
     <Shortcut Command="ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance" Scope="전역">Ctrl+Alt+F6</Shortcut>
     <Shortcut Command="View.ErrorList" Scope="전역">Ctrl+1</Shortcut>
     <Shortcut Command="View.Output" Scope="전역">Ctrl+2</Shortcut>
     <Shortcut Command="View.FindResults1" Scope="전역">Ctrl+3</Shortcut>
     <Shortcut Command="View.CodeDefinitionWindow" Scope="전역">Ctrl+4</Shortcut>
     <Shortcut Command="File.GetLatestVersion" Scope="전역">Alt+1</Shortcut>
     <Shortcut Command="CheckIn" Scope="전역">Alt+2</Shortcut>
     <Shortcut Command="View.PendingCheckins" Scope="전역">Alt+3</Shortcut>
    </UserShortcuts>
[/code]

,
Technical Article 2009. 1. 15. 14:39

OpenSSL 0.9.8j Window에서 빌드 방법

What about OpenSSL

C기반 오픈소스 암호화 라이브러리


설치준비

openssl-0.9.8j.tar

http://www.openssl.org/source/openssl-0.9.8j.tar.gz


Active Perl (ActivePerl-5.10.0.1004-MSWin32-x86-287188.msi)

http://www.activestate.com/store/download.aspx?prdGUID=81fbce82-6bd5-49bc-a915-08d58c2648ca


Nasm

http://www.nasm.us/pub/nasm/releasebuilds/2.06rc2/nasm-2.06rc2-win32.zip


빌드방법 (Windows + Visual studio 2005 )

1] Microsfot Visual Studio 2005 - Visual Studio 2005 Tools - Visual Studio 2005 명령 프롬프트 실행

2] C:\OpenSSL_Install\openssl-0.9.8j\crypto\x509v3\v3_pcia.c 를 Visual studio로 열어서 주석부분을 지운후 유니코드(949)로 다시 저장한다.
v3_pci.c, v3_pica.c 를 C:\OpenSSL_Install\openssl-0.9.8j\crypto\x509에 복사한다!

3] C:\OpenSSL_Install\openssl-0.9.8j에서

perl Configure VC-WIN32

ms\do_ms

static library 생성은   nmake -f ms\nt.mak

dll 생성은 nmake -f ms\ntdll.mak


4] 빌드가 성공하면 out32, inc32 에 프로젝트에서 사용할 library와 include할 헤더가 생성된다.


5] 제대로 빌드가 되었는지 확인하기 위해

C:\OpenSSL_Install\openssl-0.9.8j\out32 에서

..\ms\test

실행한다.

,
Technical Article 2008. 1. 31. 01:39

cximage를 통한 화면 캡쳐 및 jpg 저장

당장에 급하게 써야하는데 뭐 이래저래 구현할꺼 없이
cximage만 써서 캡쳐해서 jpg로 저장하기 쪼가리 코드!!!

버젼 : vs2005 + cximage599c_full_unicode

include : .\cximage599c_full_unicode\CxImage
library :
./cximage599c_full_unicode/png/Debug/png.lib
./cximage599c_full_unicode/jpeg/Debug/jpeg.lib
./cximage599c_full_unicode/zlib/Debug/zlib.lib
./cximage599c_full_unicode/tiff/Debug/tiff.lib
./cximage599c_full_unicode/j2k/Debug/j2k.lib
./cximage599c_full_unicode/jbig/Debug/jbig.lib
./cximage599c_full_unicode/jasper/Debug/jasper.lib
./cximage599c_full_unicode/cximage/Debug/cximage.lib

HDC dstDC = ::GetDC(NULL);
 HDC srcDC = ::GetWindowDC(m_pHtmlView->GetSafeHwnd()); ///< 캡쳐할 핸들
 HDC memDC = ::CreateCompatibleDC(dstDC);

 RECT rt;
 m_pHtmlView->GetClientRect(&rt);

 HBITMAP bm = ::CreateCompatibleBitmap(dstDC, rt.right,rt.bottom);
 HBITMAP oldbm = (HBITMAP)::SelectObject(memDC, bm);
 ::BitBlt(memDC, 0, 0, rt.right,rt.bottom, srcDC, 0, 0, SRCCOPY);

 CxImage img;
 img.CreateFromHBITMAP(bm);
 img.SetJpegQuality(80);  
 img.Save(_T("test.jpg"), CXIMAGE_FORMAT_JPG);

 ::DeleteObject(SelectObject(memDC, oldbm));
 ::DeleteObject(memDC);

,
Technical Article 2007. 12. 27. 03:03

SP Dispatcher에 대해...

어느 정도 네트웍 엔진의 골격을 잡고 최근 DB프로그래밍쪽에 많은 시간을 할애하고 있다.

Cache DB로 완전한 전환을 하기 전에 구현된 SP(Stored Procedure)들에 대해 스키마를 얻어오고 그 정보를 토대로 ATL Consumer Wizard의 Accessor 생성기와 유사한 형태의 코드 제네레이터를 만들었다.

sp이름을 통해 parameter와 column의 타입, 이름, 길이를 얻어서 생성하고 맵핑까지 끝냈는데... 앗싸 좋쿠나 하고 있던 찰라 문제가 발생했다.
 
insert와 update에 대해서 까지 미쳐 생각이 닿지 못했다.

PK가 먹어 있는 테이블에 insert를 더미값으로 집어넣으니 integratviloation이 뜰수밖에 ㅡ_ㅡ;


초기에 생각했던 sp구조 데이터를 토대로 boost::spirit을 이용해서 파싱해서 생성하는 방법으로 돌아가게됐다. 대신에 기존의 DBA가 작업하던 엑셀 시트에서 약간의 변형된 형태로 사용하는 구조로 번거로움을 줄이면서 작업하는 방향으로 합의를 봤다..


지금 시간 새벽 3시 ...

4시까지 하면 다 할수 있을꺼 같은데 ...^^;
,
Technical Article 2007. 11. 19. 09:16

Visual Studio Project에서 VSS(소스 세이프) 제거하기

[노가다 방법]

1. 읽기전용 속성 제거
2.  *.scc 파일과 *.vssscc 파일, *.vspscc 파일을 제거
3. sln 파일을 텍스트에디터로 불러
GlobalSection(SourceCodeControl) = preSolution
..
EndGlobalSection  (첫번째 나오는..)
까지 지운다

4. vcproj 파일을 텍스트에디터로 불러
SccProjectName="SAK"
SccAuxPath="SAK"
SccLocalPath="SAK"
SccProvider="MSSCCI:Microsoft Visual SourceSafe"
이 부분을 지운다


[쉬운방법]

사용자 삽입 이미지





툴바에 "소스제어"를 추가하면 소스제어 변경 아이콘(제일 앞에 선택된거)이 보인다.

클릭하면 솔루션, 프로젝트 별로 바인딩상태가 보이는데, 바인딩/해제 를 할수있다.

-_- 노가다 즐~

,
Technical Article 2007. 9. 28. 22:58

OLEDB의 Connection Pool에 대한 기본값 사용시 4가지 방법에 대한 수행속도 비교

MSSQL2K와 OLEDB Provider를 사용하여 VS6기반 ATL을 사용하여

OLEDB Wrapper를 구성해서 게임용 DB서버에서 사용하고 있었다.


올 중순부터  VS2005로 넘어오고 MSSQL2005로 바꾸면서,

기존의 네트워크 모듈부분을 뜯어고치면서

부분적으로 COM으로 구성하던 중,

DB쪽을 손보면서 OLEDB Wrapper에 대해 코드 리뷰를 하게 되었다.


기존 구조에서는 DBMS와의 연결은 단일하게 하고

Session을 DataSource에서 얻어와서 Accessor에서 사용하는 방식이였다.

즉, Stored Procedure나 query가 호출될때 session을 새로 생성하는 방식이다.

당시에는 MSSQL2K에서 Connection Pooling을 기본적으로 지원하기 때문에

Connection에 대해 크게 신경을 안쓰고 작성 했었는데, 이부분이 살짝 걸리긴 했다.

다른 방식에 대해서 성능 테스트를 해보지 못하고,

시간에 쫒겨서 만들었기 때문에  한번 검증해 보고자 테스트 코드를 만들어봤다.



환경은 Windows XP+SP2, MSSQL2005+SP1,

VS2005+SP1, MS OLEDB Provier for SQL Server 이다.

Connection스트링에 대한 옵션은 default값으로 하였다.

4가지 경우에 대한 성능 테스트를 진행해보았다.

공통적인 부분은 스레드 2개를 통해 SP(Stored Procedure)를 호출하는 consumer를 통해

recordset을 fetch하는 부분이다.

* TACCSSOR는 CCommand<CAccessor<CS_SP명> >을 상속한 클래스 인스턴스

 Case1>  Wizard를 통해 생성된 ATL OLEDB 소비자(consumer)를 그대로 사용 했다.
 ThreadFunc1()
 {
  TACCSSOR.OpenAll();  
 ...read...
 TACCSSOR.CloseDataSource();
 }

 Case2> DataSource 연결 1개. DataSource를 통해 Session 연결 1개.
 ThreadFunc2()
 {
 TACCESSOR.Open(미리 생성해둔 Session전달);
 ...read...
 TACCESSOR.Close();
}

 Case3> DataSource 연결 1개.  세션은 매번 생성
 ThreadFunc3()
 {
 CSession  session;
 _session.Open(DataSource); // DataSource를 인자로  Session생성
 TACCESSOR.Open(미리 생성해둔 Session전달);
 ...read...
 TACCESSOR.Close();
}

Case4> DataSource 연결1개, 자체 세션 풀 구성
ThreadFunc4()
{
CSession *pSession = GetSession();
 TACCESSOR.Open(*pSession);
 ...read...
 TACCESSOR.Close();
FreeSession(pSession);
}

즉, 기존에 구성했던 방식은 Case2에 해당된다.

과연 어떤 결과가 나올것인가?? 하하하~ 흥분 흥분 *--*;;

각각의 케이스에 대해 ThreadFunX를 1000회씩 실행한 결과이다.


const int DBPOOL_CASE = 1;   // 9567, 9511, 9560
const int DBPOOL_CASE = 2;   // 4388, 4402, 4375
const int DBPOOL_CASE = 3;   // 1162, 971, 977
const int DBPOOL_CASE = 4;   // 470, 530, 468

왜 이런 결과가 나온것일까??

Case1의 기본으로 생성해주는 consumer코드는 매번 DataSource를 연결하지만

Connection Pool이 구성되어 있다면 Case 2와 크게 차이가 없어야 맞다.

하지만, OpenAll 메소드 안에서 Propertie들에 대해 셋팅하는 부분과 OpenRowset을 호출하는

몇단계의 함수콜이 더 들어가게 된다. 이부분에서 시간을 소요하게 되는것이다.

Case2가 Case3보다 느린이유는 DataSource와 Session을 단일하게 사용하게 되면서

Bottle neck이 발생했다고 보는게 맞다.

(추가적으로 얻을수 있는 정보는 Session이 하나라도 자동적으로 Serialize되기때문에
 
 lock이 필요 없다는것. ^^)

Case3은 세션을 Datasource에서 가져오기 때문에 사용중인 세션에 SP를 호출하는

우를 범하지 않아서 계속 지역변수로써 Session을 생성하지만 더 빠른것이다.



Connection Pool을 직접적으로 체감하기 위해 스레드생성 이전부터 루프를 돌려 테스트를 진행해 보았다.

10회 // 4296, 3285, 1082, 588
20회 // 8801, 5908, 2118, 1089
50회 // 21883, 7544, 3257, 2585

잼있는 결과가 나온다.

자동으로 생성해준 코드가 DataSource와 Session을 미리 연결해놨을때 보다

훨씬 빠른 속도를 보여준다.

왜 이런 결과가 나온것일까?

DataSource와 Session을 단일하게만 사용했기때문에 Pool을 제대로 활용 못한 결과이다.

즉, DataSource와 Session을 매번 생성하는 Case 1의 경우 Pool을 제대로 활용했기때문에

Case1보다 빠른 성능을 보여준다.

하지만 Case3이 가장 빠를수 밖에 없는 이유는 Connection Pool도 활용하면서

선형적인 작업에는 Session Pool이 사용되는 구조이기 때문에 좋은 성능을 보여준다.

Case4는 Session을 미리 생성해두고 사용하기 때문에 지역변수가 Stack쌓이고 정리되는

과정을 줄여 속도를 높이고 있다.



결론적으로, DataSource는 하나로, Session은 필요할때(SP나 Query를 호출할때)

생성해주는게 좋은 성능을 보여준다.

게다가  Session또한 Pool로 구성하면 더욱 좋은 성능을 낼수 있다.



< vector를 이용해 Session Pool을 구현한 급조 소스 >






추가적으로 ...

<< Connection Pool에 대한 기본 개념  >>

Pool?  자료나 공간에 대해 미리 구성을 한뒤에 뽑아서 사용하고 다시 집어넣는 형식을 말함.

Connection Pool? 상호간의 연결에 대한 풀을 구성해놓고 접속을 재사용하는것.

MSSQL에서의 Connection Pool의 특징

1. Database Connection에 대한 풀.
  즉, OLEDB Provider 기준으로 보자면 CDataSrc에 해당한다.

2. 프로세스 단위로 구성
  각 풀은 프로세스 마다 풀을 구성하게 된다.

3. default값으로 Connection pooling 한다.

조건? Connection String부분이 blank하나까지도 동일해야 한다.
        (UDL파일을 사용하여 실수를 줄일수 있다)

,
Technical Article 2007. 9. 26. 21:21

wchar_t 타입을 받는 형식라이브러리 빌드 문제 C2664 Part 2

MIDL의 파싱 오류라고만 치부하기에는 MSDN의 샘플코드도 문제가 있었다.

이전글에서

 HRESULT hr = m_pSpMgr->S_AddUser( (unsigned short*)("first112"), 0, (unsigned short*)("what"), (unsigned short*)("whatu"));


이런 코드를 사용했는데 TCHAR* 를 이용해서 인자를 전달하지 않고 위에 처럼

문자열 상수를 사용하게 되면 유니코드로 들어가는게 아니라,

일반 ansi char로 인자가 전달되게 된다.

사용자 삽입 이미지
( 이 이미지는 what에 해당하는 부분이 아예 제대로 값이 전달 안되었는데 실제로는 what 0x00 4개가 전달된다 )

제대로 전달하기 위해서 코드는 다음과 같이 해야하며,

 HRESULT hr = m_pSpMgr->S_AddUser( (unsigned short*)_T("first112"), 0, (unsigned short*)_T("what"), (unsigned short*)_T("whatu"));



좀더 C++ 스럽게 표현하면

  HRESULT hr = m_pSpMgr->S_AddUser(reinterpret_cast<unsigned short*>(L"first112"),
           0,
           reinterpret_cast<unsigned short*>(L"what"),
           reinterpret_cast<unsigned short*>(L"whatu"));


이와 같이 해야 맞을것이다.

,
Technical Article 2007. 9. 26. 20:51

wchar_t 타입을 받는 형식라이브러리 빌드 문제 C2664

#include "stdafx.h"
#import "progid:BWDBAgent.SPMgr.1" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
 ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 {
  ISPMgrPtr m_pSpMgr;

  m_pSpMgr = ISPMgrPtr(__uuidof(CSPMgr));

  HRESULT hr = m_pSpMgr->S_AddUser(_T("first1"), 0, _T("what"), _T("whatu"));

 }
 ::CoUninitialize();
 return 0;
}

위와 같은 간단한 코드를 빌드하는데

..\bwdbagenttester\bwdbagenttester.cpp(15) : error C2664: 'ISPMgr::S_AddUser' : 매개 변수 1을(를) 'const wchar_t [7]'에서 'unsigned short *'(으)로 변환할 수 없습니다.
1>        가리킨 형식이 관련이 없습니다. 변환하려면 reinterpret_cast, C 스타일 캐스트 또는 함수 스타일 캐스트가 필요합니다.

이런 에러가 발생하였다.


COM 인터페이스는 다음과 같다.

__interface ISPMgr : IUnknown
{
 [helpstring("메서드 S_AddUser")] HRESULT S_AddUser([in] wchar_t* userid, [in] LONG usertype, [in] wchar_t* password, [in] wchar_t* nick);
};

저번에도 봤었는데 가물가물해서 정리해놓는다.


MSDN에 보면

midl 컴파일러에 있는 버그로 인해 wchar_t 형식이 형식 라이브러리에서 부호 없는 short로 생성됩니다. 이 오류를 해결하려면 C++ 소스 코드에서 형식을 캐스팅하거나 idl 파일에서 형식을 문자열로 정의해야 합니다.




  HRESULT hr = m_pSpMgr->S_AddUser((unsigned short*)("first1"), 0, (unsigned short*)("what"), (unsigned short*)("whatu"));

이렇게 하면 된다.

되도록이면, BSTR을 사용하는게 나을듯 싶다.

최대한 고치지 않고 부분만 빼낼려고 했더니원 -_-;;

,
Technical Article/펌 2007. 9. 15. 19:14

서버 구현할꺼~

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력해주세요.

TOTAL TODAY