사용자 삽입 이미지


코드는 lua_tinker의 샘플에 있는 코드를 토대로 내가 조금 수정했다.

예전에는 콘솔에서 프롬프트를 출력하고 대화형 IO 처리를 하기 위해서 적지 않은 분량의 코드를 직접 작성했는데
이제는 lua_interpreter 갖다 붙이고, 도움말 출력 코드도 직접 작성하는 대신 위에 있는 저 lua 함수를 쓰고나니 이제 콘솔 인터페이스는 전혀 신경쓸것 없이 메인 로직만 작성하면 그만이다.

devnote 블로그에서 console IO 처리를 위한 코드를 올려 두었었는데, 이제 아무짝에도 쓸모없겠군 +_+...
Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

사용자 삽입 이미지

콘솔 기반으로 제작된 서버 프로그램은 두가지 단점이 있습니다.

1. windows 2000 에서 실행할 경우, 마우스로 콘솔창을 클릭하면 프로세스가 bolck 되어버림 (눈으로 식별하기 힘듦.)
2. 현재 프로그램 기반에서, 엔터키를 한번 입력받으면 릴리즈 처리하고 종료됨.

1번 같은 경우, 윈도우 xp의 콘솔창은 그렇지 않습니다. 제가 xp를 쓰는데, xp의 콘솔창은 마우스 클릭을 받아도 블록되지 않더군요.
2번 같은 경우는 코드를 간단하게 수정하면 쉽게 해결할 수 있습니다.

WR 서버 같은 경우 위의 단점들을 보완하기 위해 처음에 MFC 기반의 프로젝트로 컴파일 했었습니다만,
알 수 없는 이유로 서버가 자꾸 죽어서 다시 콘솔 프로젝트로 돌아왔습니다.
아직 정확한 원인은 모르지만, 아마도 MFC에서 정의된 매크로와 동일하게 정의한 매크로 (TRY, ASSERT, VERIFY, DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC 등등...) 들이 충돌을 일으키면서 오작동을 하지 않았나 하고 추측해봅니다.

현재 WR 서버는 MFC프로젝트 정의 매크로와 동일한 매크로들을 모두 변경했고, 나중에 기회를 봐서 한번 더 MFC 기반으로 수정해볼 예정입니다.

본론으로 들어가서, 현재 콘솔프로젝트 기반에서 엔터키 입력에 종료되지 않게 수정해봅시다.
WR 서버는 콘솔에 'end'라고 입력해야 릴리즈 작업에 들어갑니다.
뿐만 아니라 usernum으로 현재 접속자 수 확인, / 으로 공지 메세지 전달, not로 섭다 알림 메세지 전달, setlog로 실행중에 로그 레벨 변경 등 고유 명령어들로 추가기능들을 수행할 수 있습니다.

우선 Winservice.cpp의 149 line 근처로 가보면 getchar() 함수가 있습니다.
이곳에서 메인 스레드가 블록되어 있다가 엔터키를 입력받으면 이 함수에서 풀려나죠.
그러면 ParseCommandLine()함수를 빠져나오고, 전체 프로그램이 종료절차에 들어갑니다.

getchar()가 적혀있는 곳에 콘솔로 부터 입력을 받아 적절한 기능을 호출해주는 '가상'함수를 호출해줍니다.
WR은 ProcessInput()라는 가상 함수를 호출합니다.
그리고 KGCGameServer를 상속받은 하위 클래스에서 ProcessInput 함수를 구현합니다.
WR에서 쓰는 파일을 첨부합니다. 참고하세요.

무지무지 단순간단심플합니다.

void KConsolServer::ProcessInput()
{
    Sleep( 1000 );

    GetCommand();

    while( m_msgIn[0].compare( "end" ) != 0 )
    {
#   define ON_ACTION( command, func ) if( m_msgIn[0].compare( #command ) == 0 ) func()
        ON_ACTION( usernum,   GetUserCount );
        ON_ACTION( /,         SendNotMsg );
        ON_ACTION( not,       NotShutDown );
        ON_ACTION( recon,     ReconnectDB );
        ON_ACTION( setlogl,   SetLogLevel );
        GetCommand();
    }
#   undef ON_ACTION
}

void KConsolServer::GetCommand()
{
    static TCHAR szbuff[MAX_PATH] = {0};

    m_msgIn[0].erase();
    m_msgIn[1].erase();

    cout << m_strName << "> ";
    cin.getline( szbuff, MAX_PATH );

    TCHAR* ptrTok = _tcstok( szbuff, " " );
   
    if( ptrTok == NULL )
        return;

    m_msgIn[0] = ptrTok;

    ptrTok = _tcstok( NULL, "\n" );

    if( ptrTok == NULL )
        return;

    m_msgIn[1] = ptrTok;

}
Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요