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


한 3주전쯤 1, 2권을 다 읽었다.

이 책을 다 읽을줄은 최근까지 생각도 못해본것 같다.

하지만 다 읽었다.

내용이 다 이해 되진 않았다 ^^

하지만 난 생각한다.

이 ACE를 2년안에 모두 이해 및 응용을 마음대로 할 수 있는 실력이 된다면

어디에 가서도 자신이 있을거라는걸

그리고 내 실력도 업그레이드 될 거라는거

대략적으로 Volume 1을 읽을때와 비교한다면

1권과 많이 틀리다고 말하고 싶다^^

상당히 틀리다.

뭐.. 하지만 못읽을정도는 아니니 괜찮다.

지금은 "ACE 프로그래머 가이드"를 코딩을 하면서 천천히 읽고 있다


현재 172페이지를 읽고 있다

이 책을 천천히 시간을 가지고 읽을 생각이다

사실 C++ Network Programming Volume 1, 2 는 급하게 읽었다.

약 30~40일 사이에 읽은것 같다.

ACE... 상당히 매력이 있는 네트워크 프레임워크다.

C++의 매력과 객체의 매력, 디자인 패턴의 매력을 느낄수 있는 책이다.^^

C++ 네트워크를 하는 사람의 목표중 하나가 될수 있다고 믿는다^^
strcpy_s의 두번째 인자에 _TRUNCATE가 들어가면 어떤 현상이 일어날까?

_TRUNCATE의 값은 unsigned int의 최대값 즉 약42억(정확히 42 9496 7295) - 4G - 값이므로 무한대라고 할수 있다.

strcpy_s( a, _TRUNCATE, b) --> strcpy_s( a, 42억, b)..

결론은 strcpy_s를 strcpy로 바꿔버리는 현상(첫번째 인자 버퍼는 보호하지 않음)이 일어난다.
예제 소스
#include <string.h>
#include <iostream>

using namespace std;

int main( int, char *[] )
{
    char    c[16];
    char    a[4];
    
    const char *  b = "012345678901234567890";

    cout << "\n====== memset ======\n";

    memset( a, 'A', sizeof(a) );
    memset( c, 'C', sizeof(c) );

    cout.write( a, _countof(a) ) << endl; // AAAA 출력
    cout.write( c, _countof(c) ) << endl; // CCCCCCCCCCCCCCCC 출력

    /* 예외 발생
    strcpy_s( a, _countof(a), b );
    cout.write( a, _countof(a) ) << endl;
    cout.write( c, _countof(c) ) << endl;
    */ 
    
    cout << "\n====== strcpy_s ======\n";
    strcpy_s( a, _TRUNCATE, b );
    cout.write( a, _countof(a) ) << endl; // 0123 출력
    cout.write( c, _countof(c) ) << endl; // buffer Overflow

    return 0;
}


출력

====== memset ======
AAAA
CCCCCCCCCCCCCCCC

====== strcpy_s ======
0123
234567890    -----> over flow

뱀다리) _TRUNCATE 의 값은 #define _TRUNCATE ((size_t)-1) 이다
그리고 size_t는 unsigned int 형이므로 _TRUNCATE 값은 unsigned int 의 최대값 대략 42억(정확히 42 9496 7295)의 값을 가집니다.

+ Recent posts