Reactor::run_reactor_event_loop 종료후에 다시 Reactor를 썼더니 문제가 일어났다.

문제는 Reactor::notify(handler,mask) 호출이 되지 않는 문제가 발생하여

ACE_Reactor_Notification_Strategy 클래스가 작동을하지 않았다.

그래서 Reactor::reset() 를 호출해봤지만 되지 않았다.

결론은 ACE_Reactor::instance()->reset_reactor_event_loop();

이걸로 해결되었다. ㅎㅎ
게임을 제대로 재밌게 하는 방법을
마비노기라는 게임을 통해서 어느정도 파악한것 같다

최근 심리학책을 3번째 읽었다.

그리고 마비노기 게임속에 심리학적인 면이 있다고 생각되었다.

게임은 일단 재미있어야 한다.
하지만 오랫동안 지속적으로 재밌는것은 힘들다.

그 중간 중간에 심리학적으로 재밌게 만들어 아니 사실은
게임 사용자들이 게임에서 빠져 나갈수 없게 만드는 요소를 집어넣어야 한다.

그것을 마비노기 게임에 있는것 같다.

바로 노가다 같은 스킬 얻기이다.
하지만 그 노가다 같은 스킬을 얻으면 게임은 재밌어지고 그전보다 하기도 수월해 진다.

이는 심리학적으로도 확인이 된다.
어느 학교 기숙사에서는 기숙사에 들어가기 위한 학생들만으로 만들어진 절차가 있다고 한다.
예를 들면 한 겨울에 속옷만 입힌채로 산 중간에 버려져서 기숙사로 돌아오기
일정한 크기로 잘려진 생 날간을 먹기 그리고 선배들에게 둘려쌓여 폭행을 당하기

일반적으로 생각하면 폭행집단이 아닌가로 생각되지만
실상은 아주 훌륭한 학교의 기숙사라고 한다.
그들은 학교생활에 적극적이며 학교 생활에 만족하며 산다고 한다.

이는 어떤 일은 하는데 있어서 고통을 겪고 나서 얻은 결과물은
자기에게 더욱 크게 느껴지고되고 만족감도 높다라고 느껴지는것이라고 한다.

이게 게임속에 있다.
마비노기 중에 "윈드밀", "제련" 스킬이 있는데 이것들이 이에 해당되지 않나 싶다.
"윈드밀" 스킬을 마스터(1랭)하는데 엄청난 노가다를 해야한다.

아마 내가 순수 윈드밀 스킬로 마지막타로 죽인 몬스터 수가
아마 3만 마리는 된거같다(정확하지 않으니 참고만^^)
이걸 마스터 할려고 몇달을 고생했다(주말족이라 토, 일요일만 했습니다^^)

하지만 마스터 하고 나서는 신천지가 되었다.
게임하는데 하기전과 엄청나게 수월해졌다.
특히 이스킬은 2랭크와 1랭크와 차이가 어마어마 한데

그게 또한 심리학적으로도 고차원적인 생각으로 만들어진것 같은 기분이든다.
이 게임의 이 스킬을 기획한 기획자를 만나서 이야기를 듣고 싶다^^

게임과 심리학.. 이건 엄청난것 같다^^

리니지같은 게임에도 심리학이 있는것 같다.
리니지는 레벨과 레벨사이의 차이가 엄청나다고 들었다.

불과 레벨 1차이로 1:5~10 도 능히 처리가 가능하다고 들었다.
1레벨을 획득하면 자신에게 엄청난 해택이 주어진다.

그리고 웃기는 것은 아니 놀라운 사실은
이것을 게임이 아닌 실 생활에도 나의 생활에도 적용할수 있다는것이 놀랍다.

자기가 하는것을 좀더 재미있게 하는데에 쓸수 있다.
바로 자기가 하는일 중 정말로 힘들게 노력해서 어떤것을 얻을수 있다면
도전해 보는것도 그중 하나가 아닐까?


230 글라디우스 개조방법
 개조 방식 : 레이널드식 - 경량화 - 경량화 - 니커식 개조 - 니커식 개조



230 글라디우스 추천 인챈드(초보, 가격싼 위주)
 인챈드  효과  입수방법
 폭스(접두) 최대대미지 +1~4, 최소대미지+1~2  키아 일반, 하급, 메탈스켈레톤
 황옥(접두) 최대대미지 +5
 어선 낚시
 매서운(접미) 체력 +5  키아중급, 하우징 ㅡ.ㅡ
 울프헌터(접두) 최대대미지 +4~6  좀 비쌈(하우징 ㅡ.ㅡ)
거센(접두) |*****| 크리티컬 10% 증가 |*****| 룬다일반 보상, 하우징, 밑작업용 정밀한인(아래 글 참고)을 바르신 다음 바르세요.

윈드밀러를 지향한다면 크리티컬 30%에 맞추고 대미지 올리는 인챈을 사용하세요.
(제가 미쳤다고 거센발라서 ㅡ.ㅜ)


추가 ) 거센도 좋더군요 ㅡ.ㅡ;; 쌍검이라도 거센 하나 정도는 발라주세요 30% 크리 맞출려면요^^
그리고 인챈은 숙련 작업전에 바르시고 숙련을 쌓으세요.

* 정밀역은 반호르 아이데른 고급무기 탭에서 구입할수 있으며 단검류등 1만 이하에 살수 있는걸로 사세요.
  0시 12시 쯤에 전체널 돌아가면서 고급 무기 탭을 보시면 나옵니다.

* 크리티컬이 부족하시면 거센 꼬리모자(룬다 던전 일반 보상)을 구하거나 사서 도둑을 바르시고 사용하시면 좋습니다.
  1. 연결
    1. SQLAllocHandle(SQL_HANDLE_DBC, COdbcEnv::GetHandle(), &hdbc)
    2. // 네트워크 불안정 시 select() 또는 poll() 에서 발생할 수 있는 blocking을 방지하기 위한 timeout 값 설정
      SQLSetConnectAttr(hdbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(ODBC_TIMEOUT), SQL_IS_UINTEGER)
    3. // ODBC연결
      SQLConnect(hdbc,     reinterpret_cast<SQLCHAR*>(szDSN), SQL_NTS,
                                      reinterpret_cast<SQLCHAR*>(szUsr), SQL_NTS,
                                      reinterpret_cast<SQLCHAR*>(szPwd), SQL_NTS)
    4. // STMT 할당
      SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt)
    5. // 퀘리 타임아웃 설정.
      DWORD dwQueryTimeOut = ODBC_TIMEOUT; // ODBC_TIMEOUT = 20
      SQLSetStmtAttr(hstmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(dwQueryTimeOut), SQL_IS_UINTEGER)

  2. Bind 바인드
    1. SQLBindCol(hstmt, col, type, buf, bufLen, &Len))

  3. 트랜젠션 시작
    1. // 오토 커밋 비활성화
      SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 )

  4. 쿼리 설정
    1. SQLExecDirect(hstmt, szQuery, SQL_NTS)

  5. Commit or Rollback
    1. Commit
      1. SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT)
    1. Rollback
      1. SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_ROLLBACK)

  6. 리셋
    1. // 오토커밋 설정
      SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 )

  7. 닫기
    1. SQLFreeHandle(SQL_HANDLE_DBC, hstmt)
    2. SQLDisconnect(hdbc)
    3. SQLFreeHandle(SQL_HANDLE_DBC, hdbc)

  1. Connect .
    1. SQLAllocHandle( SQL_HANDLE_DBC, ... ) 함수 호출후 아래 함수 호출
    2. SQLSetConnectAttr( m_hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 );

  2. Commit
    1. SQL실행후 SQLCloseCursor 호출전에 아래 함수 호출.
    2. 아래 Rollback과 같이 호출하면 안됨.
    3. SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_COMMIT);

  3. Rollback
    1. SQL실행후 SQLCloseCursor 호출전에 아래 함수 호출.
    2. 위 Commit과 같이 호출하면 안됨.
    3. SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_ROLLBACK);

메시지 블록 생성 예제

* copy 함수 사용.
ACE_Message_Block * mb=0;
ACE_NEW_REUTRN( mb, ACE_Message_Block( 128 ), -1 );

const char * data = "testData";
mb->copy( data, ACE_OS::strlen( data ) + 1 );

* wr_ptr 사용

ACE_Message_Block * mb=0;
ACE_NEW_REUTRN( mb, ACE_Message_Block( 128 ), -1 );

const char * data = "testData";
ACE_OS::sprintf( mb->wr_ptr(), data );
mb->wr_ptr( ACE_OS::strlen(data)+1 );

풀소스
나중에 정리하겠음. 아래 첨부파일 있습니다.
개발 환경
visual c++ 2008
/*
   minizip.cpp
   Version 1.01e, February 12th, 2005

   Copyright (C) 1998-2005 Gilles Vollant

   minizip 간략화버전
// 참고자료 : http://www.winimage.com/zLibDll/minizip.html
   작성자 : fehead.tistory.com
   사용법 : minizip.exe 생성할압축파일명 압축할파일1 압축할파일2 ... 압축할파일N
   예제   : minizip.exe test.zip test.txt text2.txt
*/

#include  < stdio.h > 
#include  < stdlib.h > 
#include  < string.h > 
#include  < time.h > 
#include  < errno.h > 
#include  < fcntl.h > 
#include  < direct.h > 
#include  < io.h > 

#include "minizip/zip.h"
#include "minizip/iowin32.h"

uLong filetime(
    const char *f,                /* name of file to get info on */
    tm_zip *tmzip,             /* return value: access, modific. and creation times */
    uLong *dt              /* dostime */
    )
{
  int ret = 0;
  {
      FILETIME ftLocal;
      HANDLE hFind;
      WIN32_FIND_DATA  ff32;

      hFind = FindFirstFile(f,&ff32);
      if (hFind != INVALID_HANDLE_VALUE)
      {
        FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
        FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
        FindClose(hFind);
        ret = 1;
      }
  }
  return ret;
}

int main(int argc, char * argv[] )
{
    char    filename_try[128] = {'\0', };
    strncpy( filename_try, argv[1], sizeof(filename_try) );
    filename_try[sizeof(filename_try)-1] = 0;

    zlib_filefunc_def ffunc;
    fill_win32_filefunc(&ffunc);
    zipFile zf = zipOpen2(filename_try, 0, NULL, &ffunc);

    if (zf == NULL)
    {
        printf("error opening %s\n",filename_try);
        return 1;
    }
    printf("creating %s\n",filename_try);

    char    buf[4086];
    int err = ZIP_OK;
    for (int i = 2 ;(i < argc) && (err==ZIP_OK);i++)
    {
        int size_read;
        const char* filenameinzip = argv[i];
        zip_fileinfo zi = { 0, };

        filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);

        err = zipOpenNewFileInZip3(zf, filenameinzip,&zi,
                         NULL,0,NULL,0,NULL /* comment*/,
                         Z_DEFLATED,
                         Z_DEFAULT_COMPRESSION, 0,
                         /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
                         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                         NULL, 0);

        if (err != ZIP_OK)
        {
            printf("error in opening %s in zipfile\n",filenameinzip);
            return 1;
        }

        FILE * fin = fopen(filenameinzip,"rb");
        if (fin==NULL)
        {
            err=ZIP_ERRNO;
            printf("error in opening %s for reading\n",filenameinzip);
            return 1;
        }

        do
        {
            err = ZIP_OK;
            size_read = (int)fread(buf,1,sizeof(buf),fin);
            if (size_read  <  sizeof(buf))
                if (feof(fin)==0)
            {
                printf("error in reading %s\n",filenameinzip);
                err = ZIP_ERRNO;
            }

            if (size_read > 0)
            {
                err = zipWriteInFileInZip(zf,buf,size_read);
                if (err < 0)
                {
                    printf("error in writing %s in the zipfile\n",
                                     filenameinzip);
                }

            }
        } while ((err == ZIP_OK) && (size_read > 0));

        fclose(fin);

        zipCloseFileInZip(zf);
    }
    
    zipClose(zf,NULL);

    return 0;
}
파일첨부

출력

C:\ Total : 20002 MByte  Free : 1225 MByte
D:\ Total : 132614 MByte         Free : 26944 MByte
E:\ Total : 61443 MByte  Free : 61373 MByte
F:\ Total : 171898 MByte         Free : 156790 MByte
G:\ Total : 5130 MByte   Free : 3876 MByte
                http://fehead.tistory.com


소스

#include <windows.h>
#include <iostream>
#include <direct.h>

using namespace std;

struct ST_HDDUsage
{
    unsigned long   total;          // MByte
    unsigned long   free;           // MByte
};

class HddUsage
{
    typedef BOOL (WINAPI *GET_DISK_FREE_SPACE_EX)(
        LPCTSTR, PULARGE_INTEGER,
        PULARGE_INTEGER, PULARGE_INTEGER);

private:
    HINSTANCE       m_hInstLib;
    GET_DISK_FREE_SPACE_EX  m_pGetDiskFreeSpaceEx;

public:
    HddUsage()      :       m_hInstLib( 0 ), m_pGetDiskFreeSpaceEx( 0 )     {}
    ~HddUsage()             {       destroy();      }

    bool    init()
    {
        m_hInstLib = LoadLibrary( "kernel32.dll" );
        if( m_hInstLib == 0 )
            return false;

        m_pGetDiskFreeSpaceEx = reinterpret_cast<GET_DISK_FREE_SPACE_EX>(
            GetProcAddress( m_hInstLib, "GetDiskFreeSpaceExA") );

        if( m_pGetDiskFreeSpaceEx == 0 )
            return false;

        return true;
    }

    void destroy()
    {
        if( m_hInstLib )
            FreeLibrary( m_hInstLib);
        m_hInstLib = 0;
    }

    bool GetDiskUsage( const char * pszDrive, ST_HDDUsage * pHddUsage )
    {
        unsigned __int64 i64FreeBytesToCaller = 0;
        unsigned __int64 i64TotalBytes = 0;
        unsigned __int64 i64FreeBytes = 0;

        BOOL ret = m_pGetDiskFreeSpaceEx( pszDrive,
            reinterpret_cast<PULARGE_INTEGER>( &i64FreeBytesToCaller ),
            reinterpret_cast<PULARGE_INTEGER>( &i64TotalBytes ),
            reinterpret_cast<PULARGE_INTEGER>( &i64FreeBytes ) );
        if( !ret )
            return false;

        pHddUsage->total = static_cast<unsigned long >(
            i64TotalBytes / (1024*1024) );          // Hdd total (MByte)

        pHddUsage->free = static_cast<unsigned long >(
            i64FreeBytes / (1024*1024) );           // Hdd Free (MByte)

        return true;
    }

};

int main(int, char *[])
{
    HddUsage        hddUsage;
    if( hddUsage.init() ) {
      
        // 있는 하드 디스크만 출력.
        char    driveName[4] = "A:\\";
        for( ULONG uDriveMask = _getdrives() ; uDriveMask ; uDriveMask >>= 1 )
        {
            if( uDriveMask & 1 )
            {
                // 하드 디스크일때만 출력.
                if( GetDriveType( driveName ) == DRIVE_FIXED ) {
                    ST_HDDUsage     hdd;
                    if( hddUsage.GetDiskUsage( driveName, &hdd ) ) {
                        cout << driveName << " Total : " << hdd.total <<
                            " MByte\t Free : " << hdd.free << " MByte\n";
                    }
                }
            }
            ++driveName[0];         // 드라이브명 변경. A:\, B:\ ~~~Z:\~~
        }
    }
    cout << "\t\thttp://fehead.tistory.com\n";
    return 0;
}

부끄럽지만 거의 배꼈습니다. ㅡ.ㅡ

일단 간단하게 zip파일(여러 파일이 압축된것) 압축을 풀수 있습니다.
단순버전
// 압축 파일을 해제 한다.
bool ExtractZip( const string & zipFile, const string & dstPath )
{
    // Zip파일 오픈
    unzFile uf = unzOpen( zipFile.c_str() );

    // 첫번째 Zip목록으로 이동
    int ret = unzGoToFirstFile(uf);

    for(;;)
        {
                unz_file_info   file_info;

                // 압축된 파일명을 얻음.
                char fileName[MAX_PATH];
                ret = unzGetCurrentFileInfo( uf, &file_info, fileName, sizeof(fileName), NULL, 0, NULL, 0 );

                // 압축된 파일 하나를 연다.
                ret = unzOpenCurrentFile( uf );

                // 폴더 만들기.
                MkPath( targetFilename );

                // 파일로 쓰기.
                ofstream    ofs( targetFilename.c_str() );

                // 압축을 푼다.
                char buf[4096];
                for(;;)
                {
                        int len = unzReadCurrentFile( uf, buf, sizeof(buf) );
                        if( len == 0 )
                                break;
                        ofs.write( buf, len );
                }
                ofs.close();

                unzCloseCurrentFile( uf );

                ret = unzGoToNextFile( uf );
        }

        if(ret==UNZ_END_OF_LIST_OF_FILE)
                break;

        unzCloseCurrentFile(uf);

        unzClose(uf);

    return true;
}


전체버전
// 작성자 : fehead.tistory.com
//
// 사용법 : lunzip.exe 압축파일 압축풀디렉토리
//    예제) lunzip.exe c:\test.zip c:\tmp\test
//
// 빌드 환경 : visual c++ 2003, 2008
//
// 참고자료 : zipj03.7z http://www.kippler.com/win/zipj/
//            minizip http://www.winimage.com/zLibDll/minizip.html

#include < iostream >
#include < string >
#include < Windows.h >
#include < direct.h >
#include < fstream >
#include "unzip/unzip.h"

using namespace std;

bool ExtractZip( const string & zipFile, const string & dstPath );  // 압축파일을 해당 디렉토리에 푼다.
bool IsDirectory( const string & path );                            // 디렉토리인지 확인
bool MkPath( const string & fullPath );                             // 해당 디렉토리를 만듬.

// 메인 함수
int main( int argc, char * argv[] )
{
    if( argc != 3 )
    {
        cout << "사용법 : lunzip.exe 압축파일 압축풀디렉토리\n";
        return 0;
    }

    ExtractZip( argv[1], argv[2] );

    //ExtractZip( "d:\\test.zip", "d:\\tmp\\test" );
    return 0;
}

// 디렉토리인지 알아냄.
bool IsDirectory( const string & path )
{
    DWORD ret = GetFileAttributes( path.c_str() );
    
    if( ret == 0xffffffff)
        return false;

    if( ret & FILE_ATTRIBUTE_DIRECTORY )
        return true;

    return false;
}

// 디렉토리를 만든다.
bool MkPath( const string & fullPath )
{
    string  path = fullPath;

    // 파일경로에서 디렉토리 경로만 얻음.
    string::size_type pos = path.find_last_of( "/\\" );
    if( pos != string::npos )
    {
        path.erase( ++pos, string::npos );
    }

    // 네트워크 경로 인가? 예제) "\\192.168.0.1\test"
    pos = 0;
    if( path.compare( 0, 2, "\\\\") == 0 )
        pos = 2;

    // 상위 경로를 찾아가며 디렉토리를 순서대로 만든다.
    while( (pos = path.find_first_of( "/\\", pos )) != string::npos )
    {
        string subPath = path.substr( 0, pos++ );
        
        if(IsDirectory( subPath )==false)
            _mkdir( subPath.c_str() );
    }

    return IsDirectory( fullPath );
}

// 압축 파일을 해제 한다.
bool ExtractZip( const string & zipFile, const string & dstPath )
{
    // Zip파일 오픈
    unzFile uf = unzOpen( zipFile.c_str() );
    if( uf == 0 )
        return false;

    // 첫번째 Zip목록으로 이동
    int ret = unzGoToFirstFile(uf);

    if( ret != UNZ_OK )
        goto END;

    for(;;)
    {
        unz_file_info   file_info;
        
        // 압축된 파일명을 얻음.
        char fileName[MAX_PATH];
        ret = unzGetCurrentFileInfo( uf, &file_info, fileName, sizeof(fileName), NULL, 0, NULL, 0 );

        if( ret != UNZ_OK )
            goto END;

        // 압축된 파일 하나를 연다.
        ret = unzOpenCurrentFile( uf );
        if ( ret != UNZ_OK )
        {
            cerr << fileName << " 파일 열기 실패\n";
            break;
        }

        // TargetFilename = destPath + "\\" + "압축 풀려는 파일명"
        string targetFilename = dstPath;
        if( *targetFilename.rbegin()  != '\\' )
            targetFilename.append( "\\" );
        targetFilename.append( fileName );

        // 폴더 만들기.
        MkPath( targetFilename );

        if( IsDirectory( targetFilename ) == false )
        {
            // 파일로 쓰기.
            ofstream    ofs( targetFilename.c_str() );
            if( !ofs )
            {
                cerr << "파일 열기 실패:" << targetFilename << endl;
                break;
            }
            cout << targetFilename << " : " << file_info.uncompressed_size << "bytes\n";

            // 압축을 푼다.
            char buf[4096];
            for(;;)
            {
                int len = unzReadCurrentFile( uf, buf, sizeof(buf) );
                if( len < 0 )  
                    goto END;
                if( len == 0 )
                    break;

                ofs.write( buf, len );
            }
            ofs.close();
        }

        unzCloseCurrentFile( uf );

        ret = unzGoToNextFile( uf );

        if(ret==UNZ_END_OF_LIST_OF_FILE)
            break;
    }

END:
    if(uf)
        unzCloseCurrentFile(uf);

    if(uf)
        unzClose(uf);

    return true;
}



참고사이트
  zipj 0.3
  minizip

소스 및 실행파일
 Visual C++ 2003, 2008환경에서 개발하였습니다.
 Visual C++ 2003에서는 디버그 모드에서만 작동하더군요.( std::string 문제 발생 )





  1. 환경
    1. 가) 개발PC : Visual C++ 2008이 설치 되어있고 소스가 있는 PC.
    2. 나) PC (IP : 192.168.x.x ) : 디버깅할 프로그램이 돌아가고 있는 PC.
    3. 소스 컴파일은 Relese모드 그리고 디버그 정보 생성 옵션이 들어가 있다



  1. 나)PC에 Remote Debugging Monitor 복사(설치)
    1. 나) PC에 가)개발PC에 있는 %Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\Remote Debugger\x86 디렉토리를 복사.
      1. 나) PC    D:\Remote_Monitor 디렉토리로 복사했다고 가정.


  2. 나) PC에서 msvsmon.exe 실행

  3. 나) PC에서 msvsmon.exe 옵션 바꾸기.
    1. Tools--> Options 클릭
    2. No Authentication 선택, Allow any user to debug 선택후 적용.



  4. 나)PC에서 디버깅할 프로그램 실행

  5. 가)개발PC에 있는 Visual C++ 실행후 해당 소스 열기
    1. Release 모드 선택

  6. 가)개발PC Visual c++ 리모드 디버깅 시작
    1. VisualC++ Menu --> Tools --> Attach to Process 선택.


  7. 이제 디버깅이 시작되었습니다.

링크 : http://fehead.tistory.com/89

+ Recent posts