00 윈도우 프로그래밍 팁

Posted by 빵빵빵
2009/04/10 21:35 분류없음



00 윈도우 프로그래밍 팁

원문 :  http://kkamagui.springnote.com/pages/347952

 

들어가기 전에...


각종 윈도우 팁들 - Debug Lab

 http://www.debuglab.com/knowledge/

 

WinDBG의 심볼 경로 설정

SRV*c:\websymbol*http://msdl.microsoft.com/download/symbols  -->


VC에서 메모리 관련 디버그 명령

INIT_CRTDEBUG(); <== 메모리 누수 모니터링 시작
BREAK_ALLOC(X); <== 메모리 X 블럭 할당시 Break


VC에서 Alt-F4 막기

Alt+F4 키와 같은 메세지를 처리해주기 위해서 CWinApp 함수의 PreTranslateMessage() 를 override 해서 아래의 코드를 넣어 주면 된다.

  1. if(pMsg->message == WM_SYSKEYDOWN && pMsg->wParam == VK_F4)
    {
        return TRUE;
    }


익스플로러가 죽어도 트레이아이콘에 계속 상주시키기

  1. // 메시지 등록 과정
    UINT g_uShellRestart;
    g_uShellRestart = RegisterWindowsMessage( "TaskbarCreated" );

    // Message Map 에서
    ON_REGISTERED_MESSAGE( g_uShellRestart, OnTrayShow )

    // 메시지를 처리합니다.
    LRESULT CMyDlg::OnTrayShow( WPARAM wParam, LPARAM lParam )
    {
       // TrayIcon을 다시 보여줍니다. ShowTray는 Tray를 보여주는 함수입니다.
       m_Tray.ShowTray();
    }  -->


 Variable Argument(가변 인자)

  1. // crt_vsprintf.c
    // This program uses vsprintf to write to a buffer.
    // The size of the buffer is determined by _vscprintf.

    #include
    #include

    void test( char * format, ... )
    {
       va_list args;
       int len;
       char * buffer;

       va_start( args, format );
       len = _vscprintf( format, args ) // _vscprintf doesn't count
       + 1; // terminating '\0'
       buffer = malloc( len * sizeof(char) );
       vsprintf( buffer, format, args );
       printf( buffer );
       free( buffer );
    }

    int main( void )
    {
       test( "%d %c %d\n", 123, '<', 456 );
       test( "%s\n", "This is a string" );
    }


윈도우에서 Command Line Argument 얻기

 argc = __argc, argv = __argv 로 얻으면 된다.



윈도우 공유 폴더 로그인 시 이상한 계정으로 로그인 되는 경우

 관리도구->사용자계정->좌측 상단의 네트워크 연결관리 에서 서버와 계정을 추가한다.



툴팁 생성하기

 툴팁 생성 코드

  1.     m_clToolTip.Create( this, WS_VISIBLE | WS_BORDER );
        m_clToolTip.AddTool( this, "" );
        m_clToolTip.SetDelayTime( 100 );
        m_clToolTip.Activate( TRUE );

 툴팁 표시를 위한 메시지 릴레이 코드

  1. /**
        Enter와 Esc로 인한 종료를 막는다.
    */
    BOOL CSubPartition::PreTranslateMessage(MSG* pMsg)
    {
        if( pMsg->message == WM_KEYDOWN )
        {
            if( ( pMsg->wParam == VK_ESCAPE ) ||
                ( pMsg->wParam == VK_RETURN ) )
            {
                return TRUE;
            }
        }
  2.     // ToolTip 표시를 위해 메시지 릴레이 설정
        m_clToolTip.RelayEvent(pMsg);
        return CDialog::PreTranslateMessage(pMsg);
    }


Shell Execute로 프로그램 실행하기


  1. BOOL ExecuteProgram( String FileName, String Params, INT Flag )
    {
      SHELLEXECUTEINFO execinfo;
     
      // 실행을 위해 구조체 세트
      ZeroMemory( &execinfo, sizeof(execinfo) );
      execinfo.cbSize = sizeof(execinfo);
      execinfo.lpVerb = "open";
      execinfo.lpFile = FileName.c_str();
      execinfo.lpParameters = Params.c_str();
      execinfo.fMask = SEE_MASK_FLAG_NO_UI SEE_MASK_NOCLOSEPROCESS;
      execinfo.nShow = SW_SHOWDEFAULT;
     
      // 프로그램을 실행한다.
      int r = (int)ShellExecuteEx( &execinfo );
      if ( r == 0 ) return ( false );
     
      // 만약 Sync 플랙이 세트되었으면,
      // 실행이 종료될 때까지 기다린다.
      if ( Flag == 1 )
      {
        DWORD ec;
        do
        {
          GetExitCodeProcess( execinfo.hProcess, &ec );
          Application->ProcessMessages();
        }
        while ( ec == STILL_ACTIVE );
      }
     
      return ( true );
    }

 Open URL로 웹 연결하기

CInternetFile* pFile = NULL;
CInternetSession InetSession;
 
try
{
  pFile = (CInternetFile *)InetSession.OpenURL( "URL 주소 : http://???" );
}
catch(CInternetException *pEx)
{
  pFile = NULL;
  pEx = NULL;
  AfxMessageBox( "OpenURL Excption Error!" );
}
 
CString strData;
 
if( pFile )
{
  CString strTemp;
  pFile->SetReadBufferSize( 4096 );
 
  while( true )
  {
    if( pFile->ReadString( strTemp ) )
    {
      strTemp += "\r\n";
      strData += strTemp;
    }
    else
    {
      break;
    }
  }
}
else
{
  AfxMessageBox( "OpenURL pFile is NULL!!" );
}
 
MessageBox( strData );

윈도우에서 F1 키 막기 또는 기능 변경하기

 APP의 아래부분을 막거나 변경한다.

  1.  ON_COMMAND(ID_HELP, CApp::OnHelp)


DLL의 함수 Export시 정해진 이름으로 Export 하기

 DLL의 함수를 그냥 Export 하면 함수 이름 그대로 Export 되지 않고 기타 정보가 더 붙는다. extern을 사용하면 어느정도 해결되지만 확실한 해결책은 def 파일을 이용하는 것이다. 아래와 같이 쓰면된다.

  1. LIBRARY MyDll
    EXPORTS
       Function1=Function1
       Function2=Funciton2
  2.    Data1                 DATA <== 데이터를 외부로 Export 할때
  3.    Function3             @1   <== 서수를 같이 Export 할때
  4.    Function4             @2   NONAME  <== 서수로만 Export 할때, 함수 이름 포함 X
  5.    Function5                  PRIVATE <== lib 파일에 Function5에 대한 내용 제외, DLL에는 있음

파일(File) 및 라인(Line) 관련 매크로(Macro)

  • __FILE__ : 해당 파일 이름으로 대체
  • __LINE__ : 해당 라인 번호로 대체

  1. printf( "%d %d", __FILE__, __LINE__ );

printf 직접 구현하기

 C/C++의 Calling Convention을 보면 Stack에 파라메터를 넘긴다. 이것을 이용하여 Variable Argument List를 찾아서 넣는 방식이다.

  1. /**
     임의로 만든 printf 함수
      printf 함수의 간략버전
    */
    void kPrintf( char* pcFormat, ... )
    {
        DWORD* pdwArg;
        char vcBuffer[ 1024 ];
        int iBufferIndex;
        int iFormatIndex;
        char* pcString;
        int iLength;
  2.     // 2번째 Argument를 pdwArg가 가리키고 있다.
        pdwArg = ( DWORD* ) &pcFormat + 1;
        iBufferIndex = 0;
        iFormatIndex = 0;
  3.     // 문자열 끝까지 한다.
        while( pcFormat[ iFormatIndex ] != '\0' )
        {
            if( pcFormat[ iFormatIndex ] != '%' )
            {
                vcBuffer[ iBufferIndex ] = pcFormat[ iFormatIndex ];
                iFormatIndex++;
                iBufferIndex++;
                continue;
            }
  4.         iFormatIndex++;
            switch( pcFormat[ iFormatIndex ] )
            {
                // 16진수 출력
            case 'X':
            case 'x':
                // 10진수 출력
            case 'd':
                kDToA( vcBuffer + iBufferIndex, *pdwArg );
                iBufferIndex += 8;
                iFormatIndex++;
                pdwArg++;
                break;
  5.             // 문자열 출력
            case 's':
                pcString = ( char* )( *pdwArg );
                iLength = strlen( pcString );
  6.             kMemCpy( vcBuffer + iBufferIndex, pcString, iLength );
                iBufferIndex += iLength;
                iFormatIndex++;
                pdwArg++;
                break;
     
                // 문자 출력
            case 'c':
             vcBuffer[ iBufferIndex ] = *pdwArg & 0xFF;
             iFormatIndex++;
             iBufferIndex++;
             pdwArg++;
             break;
             
                // % 출력
            case '%':
                vcBuffer[ iBufferIndex ] = '%';
                iFormatIndex++;
                iBufferIndex++;
                break;
           
                // 그외 기타
            default:
                vcBuffer[ iBufferIndex ] = pcFormat[ iFormatIndex ];
                iFormatIndex++;
                iBufferIndex++;
                break;
            }
        }
        vcBuffer[ iBufferIndex ] = '\0';
       
        // 내부 출력함수 이용
        kPrintfInternal( vcBuffer );
    }


조사식 창(Watch)에 에러(Error) 내용 보기

 아래와 같이 입력하면 에러코드와 내용을 볼 수 있다.

  1. @err,hr

VC 6.0에서 XP 스타일 적용하기

원문 :  http://blog.naver.com/kisatsg?Redirect=Log&logNo=20004074897

① 다음 내용을 편집하신후에 프로젝트 아래의 res 디렉토리에 ApplicationManifestXMLFile 파일로 저장합니다.


./res/ApplicationManifestXMLFile

          <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
          <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
                           manifestVersion="1.0">
          <assemblyIdentity
              version="1.0.0.0"
              processorArchitecture="X86"
              name="Microsoft.Windows.YourApplication"
              type="win32"
          />
          <description>YourApplication</description>
          <dependency>
              <dependentAssembly>
                  <assemblyIdentity
                      type="win32"
                      name="Microsoft.Windows.Common-Controls"
                      version="6.0.0.0"
                      processorArchitecture="X86"
                      publicKeyToken="6595b64144ccf1df"
                      language="*"
                  />
              </dependentAssembly>
          </dependency>
          </assembly>
          
          ② resource.h 에 아래 두줄 추가
          
          #define IDR_MANIFEST  1
           #define RT_MANIFEST  24
          
          ③ .rc2 파일은 거의 손 안대시죠? 그 파일안에 다음 내용을 쳐 넣습니다.
          
          // Add manually edited resources here...
          IDR_MANIFEST RT_MANIFEST MOVEABLE PURE
                       "res\\ApplicationManifestXMLFile"
          
          ④ Instance 시작 파일에 다음 내용을 쳐 넣습니다.
          
          BOOL MoneyApp::InitInstance()
          {
            InitCommonControls();    // initialize common control library
            CWinApp::InitInstance(); // call parent class method
          
          #ifdef _AFXDLL
            Enable3dControls();      // Call this when using MFC in a
                                     // shared DLL
          #else
            Enable3dControlsStatic(); // Call this when linking to MFC
                                      // statically
          #endif
          
            // the rest of the code
          }
          
          이상입니다. 모 사실 ④번은 안해도 되는데, 원저자가 하라길래 했지요. ^^;
          


Tray Icon 관련

1.Add Tray

  1.  void CMainFrame::AddSysTray()
    {
     NOTIFYICONDATA data;
     data.cbSize = sizeof(NOTIFYICONDATA);
     data.hWnd = m_hWnd;
     data.uID = IDR_MAINFRAME;
     data.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
     data.uCallbackMessage = WM_SYSTRAYCLICKED;
     data.hIcon = AfxGetApp()->LoadIcon( IDR_MAINFRAME );
     strcpy(data.szTip , VERSION);
     Shell_NotifyIcon( NIM_ADD, &data );
    }

2.Delete Tray

  1. void CMainFrame::DeleteSysTray()
    {
     NOTIFYICONDATA data;
     data.cbSize = sizeof( NOTIFYICONDATA );
     data.hWnd = m_hWnd;
     data.uID = IDR_MAINFRAME;
     Shell_NotifyIcon( NIM_DELETE , &data );
    }

3.메시지 처리

  1. LONG CMainFrame::OnSystrayClicked( WPARAM wParam , LPARAM lParam )
    {
     CYesNoDlg dlg;
  2.     switch( lParam )
     {
     case WM_LBUTTONDBLCLK:
      //::ShowWindow( m_pVisibleWnd->m_hWnd , SW_RESTORE );
      m_pVisibleWnd->ShowVisibleFrame();
      TRACE("에루 버튼\n");
      break;
     case WM_RBUTTONDBLCLK:
      TRACE("아루 버튼\n");
      if( dlg.DoModal() == IDOK )
      {
       PostMessage( WM_CLOSE , 0 , 0 );
      }
      break;
     }
     return TRUE;
    }

4.태스크바가 다시 생성되었을 때 재등록

  1. LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
     // 만약 테스크바가 제시작 되었으면
     // 익스플로어가 한번 죽었던 것이므로..
     // 새로 Tray에 더한다.
     if( message == RegisterWindowMessage("TaskbarCreated") )
     {
      AddSysTray();
     }  
     return CFrameWnd::DefWindowProc(message, wParam, lParam);
    }

다이얼로그 기반 프로그램에서 처음 시작시 다이얼로그 안띄우기

 WM_WINDOWPOSCHANGING 메시지를 이용한다. 이 메시지는 Dialog 메시지에는 없으므로 클래스 위져드에서 메시지 쪽에 메시지 필터를 "Window"로 바꿔줘야 나온다.

  1. void CHidDlgDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
    {
        CDialog::OnWindowPosChanging(lpwndpos);
     
        // TODO: Add your message handler code here
        if(m_bShowFlag)
            lpwndpos->flags |= SWP_SHOWWINDOW;
        else
            lpwndpos->flags &= ~SWP_SHOWWINDOW;
  2. }
  3. BOOL CHidDlgDlg::ShowWindowEx(int nCmdShow)
    {
        m_bShowFlag = (nCmdShow == SW_SHOW);
        return (GetSafeHwnd()) ? ShowWindow(nCmdShow) : TRUE;
    }
  4. 출처 : Tong - luster님의 Tip통


윈도우 핸들(Window Handle, hwnd)로 클래스 이름(Class Name) 얻기

  1. int GetClassName( HWND hWnd, LPTSTR lpClassName, int nMaxCount );

 이걸 찾을려고 온 MSDN을 다 뒤졌다는.. ㅡ_ㅡa...

2009/04/10 21:35 2009/04/10 21:35

08 BSD 소켓 프로그래밍(Socket Programming) 예제

Posted by 빵빵빵
2009/04/10 21:26 전산(컴퓨터)/리눅스



08 BSD 소켓 프로그래밍(Socket Programming) 예제

원문 : http://kkamagui.springnote.com/pages/551093

http://kkamagui.springnote.com/pages/551093

들어가기 전에...


0.시작하면서...

 BSD 소켓 프로그래밍은 MFC 소켓에 비하면 쓰기가 까다롭고 알아야할 부분이 많다. 특히나 윈도우 프로그래밍을 하면 MFC 소켓에 익숙해지기때문에 까먹기가 십상이다.

 이번에 NDS 소켓 프로그래밍을 하면서 우연히 다시 볼 기회가 생겨 정리한다.


1.참고 함수들

1.1 select 함수

 Single Thread로 Multi-Socket을 컨트롤 하는 방법은 여러가지가 있겠지만, 가장 대표적인 것이 select이다. select는 아래와 같은 원형을 가지고 있다.

  1. int select(
      int nfds,
      fd_set FAR* readfds,
      fd_set FAR* writefds,
      fd_set FAR* exceptfds,
      const struct timeval FAR* timeout
    );

 select 함수는 nfds에 설정된 소켓의 수만큼 소켓을 체크하므로 반드시 가장 큰 소켓 번호 + 1의 크기만큼을 nfds로 넘겨줘야 함을 잊지 말자( ex: fd + 1 ) 

 return 값은 아래와 같은 의미를 가진다.

  • 양수 : readfds or writefds or exceptfds 중에 양수 개의 fd가 이벤트가 발생했다.

    • fds에 이벤트가 발생한 fd만 플래그가 설정되므로 FD_ISSET 매크로를 이용해서 해당 socket을 찾을 수 있다.
    • timeout에 남은 시간이 저장되므로 이를 활용하면 추가적인 처리가 가능하다
  • 0 : timeout이 되었다. timeout 값의 경우 0으로 설정되면 무한대로 대기한다.
  • 음수 : readfds에 닫힌 소켓이 있거나 기타 에러가 발생했다.

 fd_set 및 timeval은 구조체로 아래와 같은 형태를 가진다.

  1. typedef struct fd_set {
      u_int fd_count;
      SOCKET fd_array[FD_SETSIZE];
    } fd_set;
  2. struct timeval {
      long tv_sec;  // second 단위
      long tv_usec; // millisecond 단위
    };

 timeval은 위에서 보는 것 그대로 second/millisecond 단위로 설정해서 사용하면 된다.


 하지만 fd_set과 같은 경우 어떻게 사용해야할지 좀 막막하다. 다행이 이를 처리해주는 매크로가 있으니 아래와 같다.

  • FD_ZERO( fd_set* fdset ) :  fdset을 초기화. 처음에는 반드시 한번 호출해야 함
  • FD_SET( int fd, fd_set* fdset ) : fdset에 fd 소켓을 등록한다.
  • FD_CLR( int fd, fd_set* fdset ) : fdset에 fd 소켓을 삭제한다.
  • FD_ISSET( int fd, fd_set* fdset ) : fdset에 fd 소켓이 있는가 확인한다.

 자주 사용하는 매크로이니 한번쯤은 읽어두자. 자세한 사용 방법은 아래의 Linux 예제를 보면 된다.


2.윈도우(Window) 환경

2.1 서버(Server)

  1. #include <winsock2.h>
    #include <stdio.h>
    #include <string.h>
  2. #define DEFAULT_PORT 2924
    #define DEFAULT_BUFFER_SIZE 4096
  3. int main()
    {
        char Buffer[DEFAULT_BUFFER_SIZE + 1];
        WSAData wsd;
  4.     if(WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
            printf("Winsock 초기화 에러!\n");
            return -1;
        }
  5.     SOCKET ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  6.     if (ls == INVALID_SOCKET) {
            printf("소켓 생성 실패!\n");
            return -1;
        }
  7.     sockaddr_in service;
        memset(&service, 0, sizeof(service));
        service.sin_family = AF_INET;
        service.sin_addr.s_addr = INADDR_ANY;
        service.sin_port = htons(DEFAULT_PORT);
       
        if (bind(ls, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR) {
            printf("bind 실패!\n");
            return -1;
        }
       
        if (listen(ls, 1) == SOCKET_ERROR) {
            printf("listen() 실패!\n");
            return -1;
        }
  8.     SOCKET as;
  9.     printf("클라이언트 연결 대기.\n");
  10.     while (1) {
            as = accept(ls, NULL, NULL);
            if (as == SOCKET_ERROR) continue;
            printf("클라이언트 연결됨.\n");
  11.         int nbyte = recv(as, Buffer, DEFAULT_BUFFER_SIZE, 0);
  12.         if (nbyte <= 0) {
                printf("recv 에러!\n");
                break;
            }
           
            Buffer[nbyte] = '\0';
            printf("에코 : %s\n", Buffer);
  13.         send(as, Buffer, nbyte, 0);
  14.         if (strncmp(Buffer, "quit", 4) == 0) {
                printf("클라이언트의 요청에 의해 서버 종료\n");
                break;
            }
           
            closesocket(as);
            printf("클라이언트 연결 해제.\n새로운 클라이언트 연결 대기.\n");
        }
  15.     closesocket(ls);
        WSACleanup();
       
        return 0;
    }

2.2 클라이언트(Client)

  1. #include <winsock2.h>
    #include <stdio.h>
    #include <string.h>
  2. #define DEFAULT_PORT 2924
    #define DEFAULT_BUFFER_SIZE 4096
  3. int main(int argc, char** argv)
    {
        char Buffer[DEFAULT_BUFFER_SIZE + 1];
        WSAData wsd;
  4.     if (argc != 2) {
            printf ("사용법 : %s [IP 주소]\n", argv[0]);
            return -1;
        }
       
        if(WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
            printf("Winsock 초기화 에러!\n");
            return -1;
        }
       
        SOCKET cs = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       
        if (cs == INVALID_SOCKET) {
            printf("소켓 생성 실패!\n");
            return -1;
        }
       
        sockaddr_in client;
        memset(&client, 0, sizeof(client));
     
        client.sin_family = AF_INET;
        client.sin_addr.s_addr = inet_addr(argv[1]);
        client.sin_port = htons(DEFAULT_PORT);
       
        if (connect(cs, (SOCKADDR *)&client, sizeof(client)) == SOCKET_ERROR) {
                printf("connect 에러!\n");
                return -1;
        }
  5.     printf("입력 : ");
        gets(Buffer);
  6.     send(cs, Buffer, strlen(Buffer), 0);
        int nbyte = recv(cs, Buffer, DEFAULT_BUFFER_SIZE, 0);
  7.     Buffer[nbyte] = '\0';
        printf("에코 : %s", Buffer);
  8.     closesocket(cs);
        WSACleanup();
       
        return 0;
    }

3.Linux or Unix or NDS

3.1 서버(Server)

 윈도우쪽 소스를 조금 수정했다.

  1. #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
  2. int main()
    {
        char Buffer[256 + 1];
  3.     int ls = socket(AF_INET, SOCK_STREAM, 0);
        if (ls == INVALID_SOCKET) {
            printf("소켓 생성 실패!\n");
            return -1;
        }
  4.     sockaddr_in service;
        memset(&service, 0, sizeof(service));
        service.sin_family = AF_INET;
        service.sin_addr.s_addr = INADDR_ANY;
        service.sin_port = htons(DEFAULT_PORT);
       
        if (bind(ls, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR) {
            printf("bind 실패!\n");
            return -1;
        }
       
        if (listen(ls, 1) == SOCKET_ERROR) {
            printf("listen() 실패!\n");
            return -1;
        }
        int as;
        printf("클라이언트 연결 대기.\n");
        while (1) {
            as = accept(ls, NULL, NULL);
            if (as == SOCKET_ERROR) continue;
            printf("클라이언트 연결됨.\n");
            int nbyte = recv(as, Buffer, DEFAULT_BUFFER_SIZE, 0);
            if (nbyte <= 0) {
                printf("recv 에러!\n");
                break;
            }
           
            Buffer[nbyte] = '\0';
            printf("에코 : %s\n", Buffer);
            send(as, Buffer, nbyte, 0);
            if (strncmp(Buffer, "quit", 4) == 0) {
                printf("클라이언트의 요청에 의해 서버 종료\n");
                break;
            }
           
            close(as);
            printf("클라이언트 연결 해제.\n새로운 클라이언트 연결 대기.\n");
        }
        close(ls);
       
        return 0;
    }

3.2 클라이언트(Client)

 NDS에서 사용하는 예제를 조금 수정했다.

  1. #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
  2. int main(void)
    {
  3.     //////////////////////////////////////////////////////////////////////////
        // Let's send a simple HTTP request to a server and print the results!
  4.     // store the HTTP request for later
        const char * request_text =
            "GET / HTTP/1.1\r\n\r\n";
    //        "Host: www.akkit.org\r\n"
    //        "User-Agent: Nintendo DS\r\n\r\n";
  5.     // Find the IP address of the server, with gethostbyname
        // DNS를 이용해서 Name으로 IP를 얻는다.
        // 2007/10/24 현재, 아직 잘 안되는 것 같다.
        iprintf( "DNS Resolve Start\n" );
        //struct hostent * myhost = gethostbyname( "www.google.org" );
        //iprintf("Found IP Address![www.google.org] [%08X]\n",
        //        myhost->h_addr_list[0] );
     
        // Tell the socket to connect to the IP address we found, on port 80 (HTTP)
        struct sockaddr_in sain;
        sain.sin_family = AF_INET;
        sain.sin_port = htons(80);
        // Host Resolve가 끝났으면 아래와 같이 사용한다.
        //sain.sin_addr.s_addr= *( (unsigned long *)(myhost->h_addr_list[0]) );
        // 아래는 google의 IP 주소이다.
        sain.sin_addr.s_addr = inet_addr( "72.14.235.99" );  
       
        // Create a TCP socket
        int my_socket;
        fd_set readfd;
        fd_set tempfd;
        struct timeval stTime;
        struct timeval stTempTime;
        int iRet;
       
        stTime.tv_sec = 5;
        stTime.tv_usec = 0;
    Retry:
       
        my_socket = socket( AF_INET, SOCK_STREAM, 0 );
        iprintf("Created Socket!\n");
       
        iprintf( "Try To Connect\n" );
        connect( my_socket,(struct sockaddr *)&sain, sizeof(sain) );
        iprintf("Connected to server!\n");
  6.     // send our request
        send( my_socket, request_text, strlen(request_text), 0 );
        iprintf("Sent our request!\n");
  7.     // Print incoming data
        iprintf("Printing incoming data:\n");
  8.     int recvd_len;
        char incoming_buffer[256];
  9.     iprintf("Recv Start\n");
        FD_ZERO( &readfd );
        FD_SET( my_socket, &readfd );
        while( 1 )
        {
            tempfd = readfd;
            stTempTime = stTime;
            iRet = select( my_socket + 1, &tempfd, NULL, NULL, &stTempTime );
            if( iRet > 0 )
            {
                recvd_len = recv( my_socket, incoming_buffer, 255, 0 );
                iprintf("Recv End Size[%d]\n", recvd_len );
                if( recvd_len > 0 )
                { // data was received!
                    incoming_buffer[ recvd_len ] = 0; // null-terminate
                    iprintf( incoming_buffer );
                }
            }
            // Time Expired
            else if( iRet == 0 )
            {
                iprintf( "Time Expired If You Press B, Exit Receiving Process\n" );
                if( ~REG_KEYINPUT & KEY_B )
                {
                    break;
                }
            }
            else
            {
                iprintf( "Error~~!!\n" );
                break;
            }
        }
       
        iprintf("Other side closed connection!\n");
  10.     shutdown(my_socket,0); // good practice to shutdown the socket.
  11.     close(my_socket); // remove the socket.
       
        iprintf( "Press Any A Key To Retry\n" );
        while( REG_KEYINPUT & KEY_A ) ;
       
        goto Retry;
  12.     while(1);
  13.     return 0;
    }

4.마치면서...

 간단하게나마 코드 조각을 정리해 보았다. 이제 구글링할 필요없이 바로 붙여넣고 쓰면된다. 다시한번 네트워크의 세계로 빠져보자.


2009/04/10 21:26 2009/04/10 21:26

CEvent 사용하기

Posted by 빵빵빵
2009/03/31 21:14 전산(컴퓨터)



CEvent 원하는 때에 이벤트가 발생한 것처럼 신호를 보내준다 이런 코드가 있다 칠때... 어디선가... g_Event.SetEvent(); 라고 호출을 하면 저 ThreadFunc 스레드는 종료되게 된다. 위치는 요기이다.
2009/03/31 21:14 2009/03/31 21:14