태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

발췌 : 윈도우즈 API 정복 1 , 김상형(한빛 미디어)

윈도우즈는 비트맵을 곧바로 화면 DC로 출력하는 함수는 제공하지 않는다. ..(중략)
왜냐하면 비트맵은 크기가 큰 데이터 덩어리이며 따라서 출력 속도가 형편없이 느리고 화면으로 곧바로 출력할 경우 여러가지 꼴사나운 현상이 발샐할 수 있기 때문이다. 마치 파일에서 한 바이트 단위로 읽어 들이는 함수가 없는 것과 같은 이유인데 파일을 읽고 싶으면 반드시 열기 , 읽기 , 닫기의 과정을 거쳐야 한다.
( ※ 현대의 하드웨어 환경이 좋아져 비트맵을 직접 출력하는 함수가 있어도 별다른 문제가 없다. CPU의 속도가 빨라진 것도 이유이지만 , 더 주요한 이유는 요즘 출시되는 그래픽카드의 대부분이 비트맵 출력을 하드웨어적으로 처리하는 가속 기능을 제공하기 때문이다. 비트맵 출력 절차중 가장 느린 함수는 LoadBitmap 이므로 이 함수만 주의하면 된다.)

마찬가지로 비트맵도 워낙 대용량이라 직접 출력하는 함수는 제공하지 않으며 약간의 준비를 거친 후 출력해야 한다. 이렇게 준비 동작을 취한 후 출력하면 여러번 출력할 때 이미 준비된 데이터를 전송하기만 하면 되므로 출력 속도가 빠르고 예비 동작을 미리 취해 놓을 수 있다는 점에서도 유리하다.

비트맵은 화면으로 직접 출력할 수 없으며 반드시 메모리 DC에 미리 준비해 놓고 사용해야 한다.

메모리 DC란 화면 DC와 동일한 특성을 가지며 그 내부에 출력 표면을 가진 메모리 영역이다.
메모리에 있기는 하지만 화면 DC에서 사용할 수 있는 모든 출력을 메모리 DC에서도 할 수 있다. 선,면, 원등의 작도 함수는 물론 화면 DC에서는 불가능한 것까지도 가능하다. 그래서 메모리 DC에 먼저 그림을 그린 후 사용자 눈에 그려지는 과정은 보여주지 않고 그 결과만 화면으로 고속 복사하는 방법(더블 버퍼링)을 많이 사용한다.

사용자 눈에 화면이 그려지는 과정을 보여주는 것은 그리 깔끔한 모습이 아니다. 여기서 우리가 하고자 하는 비트맵 출력을 위해서도 반드시 메모리 DC를 사용해야 한다. 비트맵도 일종의 GDI 오브젝트이지만 화면 DC에는 선택할 수 없으며 메모리 DC만이 비트맵을 선택할 수 있다. 그래서 메모리 DC에 먼저 비트맵을 읽은 후 화면 DC로 복사하는 것이다.
메모리 DC를 만들때는 다음 함수가 상용된다.

HDC CreateCompatibleDC( HDC hdc );

인수로 화면 DC의 핸들을 주면 이 화면 DC와 동일한 특성을 가지는 DC를 메모리에 만들어 그 핸들을 리턴한다. (중략)
메모리 DC를 만든 후에는 비트맵을 읽어오고 이 비트맵을 메모리 DC에 선택한다. 선택할 때는 여타의 GDI 오브젝트와 마찬가지로 SelectObject 함수를 사용하며 비트맵을 읽어올 때는 LoadBitmap 함수를 사용한다.

HBITMAP LoadBitmap (HINSTANCE hInstance , LPCTSTR lpBitmapName);

[※※필기자※※  pda (windows mobile6 )같은 플랫폼에서는 SHLoadDIBitmap()함수를 사용한다. Ex.SHLoadDIBitmap(L"\\Program Files\\1.bmp") ]

DC간의 영역끼리 고속 복사 (화면출력) 를 수행하는 함수는 아래와 같다.(2가지)

BOOL BitBlt( HDC hdcDest , int nXDest , int nYDest , 
                int nWidth , int nHeight , HDC hdcSrc , int nXSrc , int nYSrc , DWORD dwRop);

BOOL StretchBit(HDC hdcDest , int xXOriginDest , int nYOriginDest , 
                        int nWidthDest , int nHeightDest ,
                       HDC hdcSrc , int nXOriginSrc , int nYOriginSrc ,
                       int nWidthSrc , int nHeightSrc , DWORD dwRop);

Posted by 갑빠돌격기

댓글을 달아 주세요


※ 함수의 원형
HGDIOBJ GetStockObject( int fnObject );
HGDIOBJ SelectObject( HDC hdc , HGDIOBJ hgdiobj );
HPEN CreatePen( int fnPenStyle , int nWidth , COLORREF crColor );

 /********************************************************************************
...
...
① 변수선언
HBRUSH MyBrush;
HBRUSH OldBrush;
HPEN MyPen;
HPEN OldPen;
...
...

② 새 브러쉬, 팬을 생성
MyBrush  = (HBRUSH)GetStockObject(GRAY_BRUSH);
MyPen     = CreatePen(PS_SOLID , 5 , RGB(0,0,255));

③ 새 브러쉬,팬 선택 및 이전 객체를 담아둠
OldBrush  = (HBRUSH)SelectObject(hdc , MyBrush);
OldPen     = (HPEN)SelectObject(hdc , MyPen);
...
//브러쉬와 펜을 사용
...

④ 원래의 GDI오브젝트로 복구
SelectObject(hdc , OldBrush);
SelectObject(hdc , OldPen);

⑤ 사용자가 생성한 팬을 삭제
DeleteObject(MyPen);
※ 한줄로 표현하면 DeleteObject( SelectObject(hdc , OldPen));
...
...
***********************************************************************************/
Posted by 갑빠돌격기

댓글을 달아 주세요

참고
- 윈도우즈 API 정복 1 [김상형 지음]


일반적으로 API함수들은 운영체제가 제공하며 프로그램에서는 이 함수들을 호출해서 운영체제의 서비스를 받는다. 예를 들어 도스의 시스템 콜 함수를 호출하여 디스크 입출력을 한다든가 윈도우즈의 TextOut함수를 호출하여 문자열을 출력하는 경우가 이에 해당한다. 응요 프로그램이 운영체제에 내장된 함수를 호출하여 원하는 작업을 하는 것이다.

  반면 콜백함수는 응용 프로그램이 제공하며 운영체제가 필요할 때 호출하는 함수이다. 홓출되는 방향이 거꾸로 되었기 때문에 콜백이라고 부르는 것이다. 굳이 우리말로 번역한다면 "거꾸로 호출되는 함수"정도로 번역할 수 있겠으나 마땅한 번역이 없으므로 그냥 원주민 발음대로 콜백이라고 부른다.

즉 "운영체제(system)에 의해 호출되는 프로그램 내부의 함수"라고 할 수 있다.
Posted by 갑빠돌격기

댓글을 달아 주세요

1. Kernel
2. USER
3. GDI   (Graphic Device Interface)
   ▶ DC (DeviceContext ) : 출력에 필요한 모든 정보를 가지는 데이터 구조
                                     : GDI 오브젝트를 모아 놓은 것
   ▶ Ex) LineTo(hDc , X , Y) - 선을 긋기 위한 정보들을 모두 모아 DC라는 구조체를 만들고
                                             LineTo함수는 X,Y값 이외에도 DC핸들을 넘겨받아
                                             그 값을 사용한다.
                                             (그리기 함수들이 참조하는 원점의 정보
                                              (스크린,윈도우 좌표)등의 정보도 제공한다.
   ▶ DC를 얻는 방법 2가지
      1. HDC GetDC(HWND hWnd);
          int ReleaseDC(HWND hWnd , HDC hDC);
          ex) HDC hdc
                hdc = GetDC(hWnd);
                /* 각종 출력문에서 hdc를 사용 */
                ReleaseDC(hWnd , hdc)
      2. HDC hdc;
         PAINTSTRUCT ps;
         case WM_PAINT:
                  hdc = BeginPaint(hWnd , &ps);
                  /* 각종 출력문에서 hdc를 사용 */
                  EndPaint(hWnd , &ps);
         ( BeginPaint는 WM_PAInT메시지 내에세 그림 그리기 준비를 하는
            좀더 전문적인 함수이되 , 그 외의 메시지에서는 절대로 사용불가)



   
                                            

Posted by 갑빠돌격기
TAG API, DC, dll, GDI, 동적

댓글을 달아 주세요

typedef struct WSAData{
     WORD                wVersion;
                                     // WS2_32.dll에서 로드된 윈도우즈 소켓의 버전
     WORD                wHighVersion;
                                     // 로드한 DLL이 지원하는 윈도우즈 소켓의 상위 버전.
                                     //    (일반적으로 wVersion인자와 동일)
      char                 szDescription[WSADESCRIPTION_LEN+1];
                                     // NULL로 끝나는 아스키 스트링 값.
                                     // (적재된 WS2_32.dll에서 소켓에 관련된 설명 문자열을 카피)
      char                 szSystemStatus[WSASYS_STATUS_LEN+1];
                                    // NULL로 끝나는 아스키 스트링 값.
                                    // (시스템의 각종 상태를 알수 있도록 해준다.)
      unsigned short    iMaxSockets;
                                    // 어플리케이션에서 사용할 소켓의 최대 수를 리턴해 주는 멤버
                                    // (version 2부터는 무시된다.)
     unsigned short    iMaxUdpDg;
                                    // 어플리케이션이 전송할 수 있는 데이터그램 최대 크기를 리턴
                                    // (version 2부터는 무시된다.)
     char       FAR     *lpVendorInfo;
                                    // (version 2부터는 무시된다.)
}WSADATA, FAR * LPWSADATA;




/******************************************************************************

// WS2_32.dll을 불러와 메모리에 적재하는 함수)

WSADATA wsadata;
if(WSAStartup(MAKEWORD(2,2) , &wsadata) == SOCKET_ERROR)
     return;

// 적재한 DLL을 메모리에서 해제하는 함수
int WSACleanup();


******************************************************************************/



Posted by 갑빠돌격기

댓글을 달아 주세요

netstat                                                                                                                 
/*현재 로컬 호스트의 네트워크 연결 상태를 보여준다. 이 명령어를 이용하면, 로컬 호스트에
  연결된 소켓의 정보나 라우팅 상태는 물론 연결을 시도 중이거나 연결된 대상을 볼수있다.*/
 
   -r  : 라우팅 테이블을 보여준다.
   -a : 모든 연결과 listening port 에 대한 정보를 보여준다.

tracert                                                                                                                 
/*목적지까지의 링크 상태를 보여준다.  목적지까지 경유하는 과정, 경유상태를 보여준다.*/

   -h  : 목적지까지의 최대 hop카운트
   -w : 응답이 오기까지의 최대 시간

ping                                                                                                                      
/*목적지까지의 네트워크의 상태를 체크한다. 즉, 목적지의 호스트가 응답하는 시간(echo)을
체크한다. 이 명령어를 통해서 목적지까지의 네트워크의 응답속도와 연결가능 여부등을 체크*/

   -n count       : 목적지에 요청할 에코의 수
   -i TTL          : Time to live
   -w time-out  : 응답을 기다릴 시간
Posted by 갑빠돌격기

댓글을 달아 주세요

NIC ( Network Interface Card )                                                            
     NIC는 네트워크상에서 다른 컴퓨터 시스템에 데이터를 보내거나 받을 때 사용하기 위한
     하드웨어를 말한다. 이런 종류의 하드웨어는 모뎀이나 랜카드 등이 해당되는데 ,
     각각의 NIC는 자신에게 주어진 유일한 식별번호를 가지고 있다.
     이 식별 번호는 네트워크에서 아주 중요하게 쓰인다.

NDIS ( Network Driver Interface Specification )                                        
     NDIS는 Microsoft 사와 3Com  사가 개발한 것으로 네트워크 장치의 드라이버를 연결하는
     일종의 인터페이스이다. 이 인터페이스를 통하여 프로그래머는 상대 시스템의 장치의
     종류에 상관없이 NDIS만을 호출하여 프로그래밍을 할 수 있도록 한다.

DAEMON (System Daemon)                                                                
     데몬은 일종의 백그라운드 작업을 의미하는 용어이다.
     네트워크에서의 데몬은 대부분이 서버인데, 서버는 보통 사용자의 접근을 계속해서
     기다려야 하기 때문에 백그라운드 프로세싱이 필요하다. 예를 들어 여러분이 아파치
     웹서버를 실행했거나 윈도우즈 2000서버 패밀리를 시스템에 사용할 경우를 생각해 보자.
     웹서버는 항상 작업중이어야 하고 , 그 작업의 상태는 여러분의 눈에 보일 필요가 없다.
     특히 윈도우즈 서버 패밀리는 각종 데몬들이 시스템 윈도우즈 부팅과 동시에 실행되는데
     telnet , ftp , http 등의 잘 알려진 서버들이 모두 데몬이다. 물론 데몬에는 서버만 존재하는
     것은 아니다.

inetd                                                                                              
     데몬은 항상 서버에서 실행된다. 데몬이 실행되면 시스템의 자원을 소비 하는데,
     만은 수의 데몬이 동시에 실행되면 상당한 자원이 낭비된다.
     만일 여러분이 윈도우즈 서버 패밀리나 리눅스를 실행해본 적이 있다면 , 수많은 데몬들이
     OS시작과 더불어 실행되고 있는 것을 본 적이 있을 것이다.
     그러나 이러한 데몬들이 모두 외부의 접근을 받아주고 있는 경우는 드물어서 시스템자원을
     낭비하는 경우가 많다. 데본들은 항상 어떤 서비스를 준비하고 있어야 하기 때문이다.
     즉, 서버는 클라이언트의 접근이 언제 이루어질지 모르므로 항시 대기하고 있어야만 한다.
     하지만 언제 접근할지도, 어느 정ㄷ도의 접근할지도 모른다. 심한 경우 하루에 단 한번
     접근할 수도 있다.
     inetd는 이런 데몬들이 시스템 자원들을 쓸데없이 낭비하지 않도록 교통 정리를 하는
     것으로 , inetd역시 데몬의 일종이다. inetd는 클라이언트의 접근이 있으면 그때서야
     필요한 데몬을 실행시킨다. 즉 , 시스템의 자원을 효율적으로 관리해 주는 데몬이다.
     그러나 반드시 inetd 가 효율적으로 만들어 주지는 않는다. 예를 들어 우리가 웹서버를
     운영할 경우 항상 램에 상주해 있는 효율적이다. 왜냐하면 우리는 우리는 웹사이트에
     사용자가 접근할 것을 예상하기 때문이다. 하지만 해당 시스템에 FTP서버를 같이 사용하는
     경우를 생각해 보면 FTP서버의 경우 일정 기간을 제외하고는 아주 사용빈도가 낮을 것이라
     예상되는 경우 inetd에 등록을 해놓는 것이 좋다. 하지만 웹서버 데몬은 등록하지 않는 것이
     좋을 것이다.

HOP ( Hop Count )                                                                            
     홉(hop)은 하나의 링크를 의미한다. 링크란 네트워크 내에서 경유하게 되는 하나의
     단계를 의마한다. 예를 들어 송신측을 출발한 패킷은 몇 번의 라우터를 거쳐 수신측에
     이르는데, 여기에서 각 라우터를 링크라고 생각하면 된다. 따라서 hop을 많이 거칠수록
     목적지를 찾는 데 오래 걸린다는 의미가 되기도 한다.
     홉 카우트는 패킷이 목적지까지 도착하는데 경유하는 링크의 수를 의미한다.
     홉 카운트는 패킷의 헤더에 기록되는데 라우터는 보통 이 홉카운트를 체크해서 비정상적
     으로 높은 패킷은 삭제를 해서 더 이상 네트워크 상에서 돌아다니지 못하게 막는다.
     이는 네트워크의 리소스가 목적지를 잃은 비정상적인 패킷들로 부하가 걸리는 것을 막아
     네트워크의 자원을 관리하려는 것이다. 특히 스트림 패킷(보통 TCP) 의 경우에는 보통
     목적지까지의 경유가 유지되지만 데이터그램 패킷(보통 UDP)의 경유에는 길을 잃은
     패킷이 많으므로 홉 카운트의 관리는 필수적이다.
Posted by 갑빠돌격기

댓글을 달아 주세요


기본적인 로비채팅 기능을 구현한 메신저.

/*****************************************
       서버는 MS SQL2005 DB연동이 필요
       SQL 인증 방식을 통한  ODBC 접속

             서버          : SeungHwan
             사용테이블 : Lobby-pj
             접속id       : sql
             접속pw     : sql-psw
******************************************/

1. 다 대 다 채팅(로비채팅) 가능
2. 친구등록후 1:1 채팅 가능
3. p2p 게임은 아직 구현하지 않음
Posted by 갑빠돌격기

댓글을 달아 주세요

/*
간단하게 구현된 1:1 방식의 채팅 프로그램이다.
실제 네트워크 어플리케이션 에서는 이러한 방법은 쓸 수 없으며,
이것은 단지 문자열에 대해서만 동작할 수 있으며
다른 종류의 데이터는 처리하는 것이 곤란하다.

1. 단일 접속만을 허용한다.
2. 한쪽은 서버 , 한쪽은 클라이언트
3. 채팅 이외의 기능은 가지지 않는다.
4. api로 구현되었다.

*/


=============================================================================
1. 실행후 wait client라는 문자열을 입력하면 Server 상태로 Client의 접속을 대기한다.
   [ 창을 보면 현재 server의 IP정보를 확인할 수 있다. ]

2. 또 프로그램을 실행후,(client)
    확인된 server의 ip주소를 입력하면 server와 접속하게 된다.

==============================================================================
Posted by 갑빠돌격기

댓글을 달아 주세요

char* ReturnMyIpAddress()
{
 int                re;
 char             name[255], *ip = NULL;
 PHOSTENT   phostinfo;

 re = gethostname(name , sizeof(name));
 if(re == 0)
 {
  if((phostinfo = gethostbyname(name)) != NULL)
  {
   ip = inet_ntoa(*(struct in_addr *)*phostinfo->h_addr_list);
  }
 }
 return ip;
}

/*****************************************************************************
gethostbyname()함수를 호출하면 인터넷 주소를 리턴받을수 있는데,
문제는 이 함수가 리턴하는 주소가 우리가 알아볼 수 있는 포맷이 아니라는 것이다.
따라서 inet_nota()함수를 통해 문자열로 변환하고, 이 변환된 주소를 함수의 리턴 값으로
사용한다.
inet_ntoa() 함수는 inet_addr()함수와는 정반대의 역할을 수행한다.
****************************************************************************/

/*****************************************************************************
gethostname()
   설   명 : 로컬 머신의 호스트 네임을 알아낸다.
   원   형 : int gethostname(char FAR * name , int namelen);
   리턴값 : 성공하면 0을 리턴한다.

gethostbyname()
   설   명 : 정보를 알고 싶은 호스트의 이름을 인자로 주면,
               해당 호스트를 검색하여 발견할 경우 HOSTENT 구조체의 포인터를 리턴한다.
   원   형 : struct hostent FAR * gethostbyname(const char FAR * name);
   리턴값 : 성공하면 HOSTENT 구조체의 포인터를 리턴하고 , 실패하면 NULL을 리턴한다.
*********************************************************************************/

Posted by 갑빠돌격기

댓글을 달아 주세요

SOCKET (소켓)
네트워크 전송에서 프로세스들의 통신을 위한 최종점 오브젝트(OBJECT) ,
소켓은 데이터 그램이나 스트림 타입이며 지정된 네트워크 주소로 묶일수 있다.
소켓은 윈도우즈 소켓 연결을 다루기 위한 어플리케이션 프로그래밍 인터페이스 (API) 를
제공한다.

SOCKET ADDRESS (소켓주소)
각 소켓 객체는 네트워크상에서 인터넷 프로토콜 주소(IP Address)로 조합된다.
보통 주소는 ftp.microsoft.com의 머신 이름이거나 "128.56.22.8"과 같이 점으로 구분되어지는
숫자로 표현된다.

/*
보통은 소켓을 만들기 위해 검색을 할 때 일일이 주소를 지정할 필요는 없다.

중요한 것은 시스템이 복수의 네트워크 카드를 사용하거나 또는 우리가 만든 어플리케이션이
언젠가는 그런 복수의 네트워크 카드를 장착한 시스템을 사용할 것이라는 점이다.

따라서 우리는 소켓이 사용될 네트워크 카드에 주소를 지정할 필요가 있다.
이것은 사용상 장점을 가지게 될 것이며 특히 휴대용 컴퓨터의 관점에서는 아주 중요하다.
*/


--------------------------------------------------------------------
가남사 "메신저와 로비 서버를 이용한 게임제작 그리고 알고리즘" 정윤철 저
Posted by 갑빠돌격기

댓글을 달아 주세요

////////////////////////////
// 08.07.21 Simple_Client.cpp
////////////////////////////

#include<WINSOCK2.h>
#include<stdio.h>

#pragma comment(lib , "ws2_32.lib")

int main()
{
 SOCKET sd;
 SOCKADDR_IN ser_addr;
 char buf[1024];
 
 WSADATA data;
 WSAStartup(0x0202 , &data);

 sd = socket(AF_INET , SOCK_STREAM , 0);
 
 ser_addr.sin_family = AF_INET;
 ser_addr.sin_port = htons(8888);
 //ser_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 ser_addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.112");
 memset(&ser_addr.sin_zero , 0 , sizeof(ser_addr.sin_zero));
 
 connect(sd,(SOCKADDR*)&ser_addr , sizeof(ser_addr));
 
 printf("message:");
 gets(buf);
 
 send(sd , buf , strlen(buf),0);
 /////////////////////////////////////
 memset(buf,0,sizeof(buf));
 /////////////////////////////////////
 int ret = recv(sd, buf, sizeof(buf),0);
 buf[ret] = 0 ;
 
 printf("[%s]\n",buf);
 closesocket(sd);
 WSACleanup();
 return 0;
}

Posted by 갑빠돌격기
TAG C, Client, Simple

댓글을 달아 주세요

/////////////////////////////
//   08.07.21 - Simple_Server
/////////////////////////////

#include<winsock2.h>
#include<stdio.h>

#pragma comment(lib, "ws2_32.lib")

int main()
{
 SOCKET sd;
 SOCKADDR_IN ser_addr;
 char buf[1024];
 
 WSADATA data;
 WSAStartup(0x0202, &data);
 
 sd = socket(AF_INET , SOCK_STREAM , 0);
 
 ser_addr.sin_family    = AF_INET;
 ser_addr.sin_port    = htons(8888);
 ser_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
 memset(&ser_addr.sin_zero, 0 , sizeof(ser_addr.sin_zero));
 
 bind(sd , (SOCKADDR*)&ser_addr , sizeof(ser_addr));
 listen(sd , 10);
 
 while(1)
 {
  SOCKET new_sd = accept(sd, 0 , 0);
  int ret = recv(new_sd , buf , sizeof(buf), 0);
  buf[ret] = 0;
 
  printf("[%s]",buf);
 
  send(new_sd , buf , strlen(buf),0);
  closesocket(new_sd);
 }
 WSACleanup();
 return 0;
}

Posted by 갑빠돌격기
TAG C, Network, Server

댓글을 달아 주세요

/*************************************************************************
Written by Seunghwan
*************************************************************************/

#include<iostream>
#include<objbase.h>
using namespace std;

//////////////////////////////////////////////////////////////////////////
interface ISimpleHelloWorld : public IUnknown
{
 virtual void __stdcall PrintHello() = 0;
};

//////////////////////////////////////////////////////////////////////////
extern const IID IID_ISimpleHelloWorld;

//////////////////////////////////////////////////////////////////////////
class SimpleHelloWorld : public ISimpleHelloWorld
{
 virtual HRESULT __stdcall QueryInterface(const IID & iid , void **ppv);
 virtual ULONG   __stdcall AddRef()
 {
  return 0;
 };
 virtual ULONG   __stdcall Release()
 {
  return 0;
 };
public:
 virtual void __stdcall PrintHello()
 {
  cout << "Hello World" <<endl;
 }
};

//////////////////////////////////////////////////////////////////////////
HRESULT __stdcall SimpleHelloWorld :: QueryInterface(const IID & iid , void ** ppv)
{
 if(iid == IID_IUnknown)
 {
  cout<< "QueryInterface : Return pointer to IUnknown." <<endl;
  *ppv = static_cast<ISimpleHelloWorld*>(this);
 }
 else if(iid == IID_ISimpleHelloWorld)
 {
  cout<< "QueryInterface : Return pointer to ISimpleHelloWorld."<<endl;
  *ppv = static_cast<ISimpleHelloWorld*>(this);
 }
 else
 {
  cout<< "QueryInterface : Interface not supported."<<endl;
  *ppv = NULL;
  return E_NOINTERFACE;
 }
  static_cast<IUnknown*>(*ppv)->AddRef();
 return S_OK;
}

//////////////////////////////////////////////////////////////////////////
IUnknown* CreateInstance()
{
 IUnknown* pI = static_cast<ISimpleHelloWorld*>( new SimpleHelloWorld );
 pI->AddRef();
 return pI;
}

//////////////////////////////////////////////////////////////////////////
static const IID IID_ISimpleHelloWorld =
// {D035B70E-55A1-4869-808E-C395C4964C54}
{ 0xd035b70e, 0x55a1, 0x4869, { 0x80, 0x8e, 0xc3, 0x95, 0xc4, 0x96, 0x4c, 0x54 } };


//////////////////////////////////////////////////////////////////////////
void main()
{
 HRESULT hr;

 cout << "Client : Get and IUNknown pointer."<<endl;
 IUnknown * pIUnknown = CreateInstance();

 cout << "Client : Get interface ISimpleHelloWorld"<<endl;
 ISimpleHelloWorld * pISimpleHelloWorld = NULL;
 hr = pIUnknown->QueryInterface(IID_ISimpleHelloWorld , (void**)&pISimpleHelloWorld);

 if(SUCCEEDED(hr))
 {
  cout<<"Client : Succeeded getting ISimpleHelloWorld"<<endl;
  pISimpleHelloWorld->PrintHello();
 }

 delete pIUnknown;
}

Posted by 갑빠돌격기

댓글을 달아 주세요

/*****************************************
  참고 : TCP/IP 소켓 프로그래밍   윤성우 | 저
******************************************/


int bind(int sockfd , struct sockaddr * myaddr , int addrlen);

      sockfd  - 주소를 할당하고자 하는 소켓의 파일디스크립터
      myaddr - 할당하고자 하는 주소 정보를 지니고 있는 구조체 sockaddr_in 의 포인터
      addrlen - 인자로 전달된 주소 정보 구조체의 길이


     결과 : sockfd가 가리키는 소켓에 myaddr이 가리키는 주소 정보 할당

Posted by 갑빠돌격기

댓글을 달아 주세요

/*************************************
참고 : TCP/IP 소켓 프로그래밍 윤성우|저
**************************************/


// 일반적인 코드
struct sockaddr_in addr;

char * serv_ip    = "192.168.0.113";
char * serv_port = "8888";

memset(&addr , 0 , sizeof(addr_len));
addr.sin_family          = AF_INET;
addr.sin_addr.s_addr = inet_addr(serv_ip);
addr.sin_port            = htons(atoi(serv_port));


// 개량형
struct sockaddr_in addr;

char * serv_port = "8888";

memset(&addr, 0 , sizeof(addr_len));
addr.sin_family          = AF_INET;
addr.sin_addr.s_addr = inet_addr(INADDR_ANY);
addr.sin_port            = htons(atoi(serv_port));

/**************************************************************************
INADDR_ANY 상수값을 이용하여 시스템의 IP를 자동적으로 찾아서 할당한다.
또한 , 두개 이상의 IP를 할당받아 사용하는 MultiHomed (ex: 라우터) 컴퓨터의 경우,
어떤 주소를 통해 들어오는 데이터를 모두 받아 들일 수 있다.
**************************************************************************/
Posted by 갑빠돌격기

댓글을 달아 주세요

/***********************************************
   참고 : TCP/IP 소켓 프로그래밍 / 윤성우 | 저
************************************************/

● unsigned long inet_addr(const char * string);
     // Dotted-Decimal Notation 을 Big-Endian 32 (network-byte-ordering) 비트 값으로 변환
    //  사용자가 return 값을 sockaddr_int 구조체의 int_add에 대입하여야 한다.

● int inet_aton(const char * string , struct in_addr * addr);
    //  inet_addr 함수 보다 개선된 데이터 변환 함수 , 인자로 in_addr의 포인터를 넘기기에
    //  사용자가 따로 값을 대입하여 줄 필요가 없다.

● char * inet_ntoa(struct in_addr addr);
   //  network-byte-ordering (32bit)값을 Dotted-Decimal Notation으로 변환하여 준다.
   //  리턴값 -> char의 포인터    
   //  문자열의 저장소 -> 함수내부의 static 버퍼
Posted by 갑빠돌격기

댓글을 달아 주세요

/***********************************************
   참고 : TCP/IP 소켓 프로그래밍 / 윤성우 | 저
************************************************/

[1]. 시스템이 내부적으로 데이터를 처리하는 방식 2가지 //

   (1). Big - Endian 표현
  ┌───┬───┬───┬───┐
  │ 0x12  │ 0x34  │ 0x56  │ 0x78  │       //ex : Motorola 68000계열
  └───┴───┴───┴───┘

   (2). Little - Endian 표현
  ┌───┬───┬───┬───┐
  │  0x78 │ 0x56  │ 0x34  │ 0x12  │      //ex : Intel X86 계열
  └───┴───┴───┴───┘

     /*
     데이터를 상이하게 처리하는 두 호스트 간의 통신에서
    주고 받는 데이터를 서로 다른 값으로 해석하지 않기 위해
    통일된 방식으로 데이터를 전송하기로 약속하였는데
    이를 "네트워크 바이트 순서 (NetWork Byte Order)" 라고 한다.
    현재 네트워크 바이트 순서는 Big - Endian 방식만을 사용하기로 약속되어 있다.
     */

[2]. 바이트 순서 변환

/*
     'h' : host      byte order
     'n' : network byte order
     's' : short     (16bit)
     'l'  : long      (32bit)
*/
ex)
htons ==>  h to n s  ==> host byte order 를 network byte orde로...short 타입으로
htonl  ==>  h to n l   ==> host byte order 를 network byte order로..long  타입으로
ntohs ==>  n to h s  ==> network byte order를 host byte order로.. short 타입으로

practice)

/////////////////////////////////////////////////
// endian_conv.c
// written by SW. YOON
// TCP/IP 소켓 프로그래밍 / 윤성우 | 저

- 컴파일시 ws2_32.lib를 추가 시켜주어야 함
/////////////////////////////////////////////////

/* source
#include<stdio.h>
#include<WINSOCK2.H>

int main()
{
 short host_port_order = 0x1234;
 short  net_port_order = htons(host_port_order);

 long host_add_order   = 0x12345678;
 long  net_add_order   = htonl(host_add_order);

 printf("    Host ordered port : %x\n" , host_port_order);
 printf(" Network ordered port : %x\n" , net_port_order);

 printf("    Host ordered Address : %x\n" , host_add_order);
 printf(" Network ordered Address : %x\n" , net_add_order);
}

/** result  *************************************
     Host ordered port : 1234
Network ordered port : 3412

     Host ordered Address : 12345678
Network ordered Address : 78563412
***********************************************/

Posted by 갑빠돌격기

댓글을 달아 주세요

/************************************************************************
helloworld_client_win.c
 Written by SW.Yoon
  참고 : TCP/IP 소켓 프로그래밍 / 윤성우 | 저

- 컴파일전 반드시 ws2_32.lib 라이브러리를 링크시켜야 한다.
- argument 값으로 <IP> <PORT> 를 넘겨줘야 한다.
************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>

void ErrorHandling(char* message);

int main(int argc , char ** argv)
{
 WSADATA  wsaData;
 SOCKET  hSocket;
 char  message[30];
 int   strLen;
 SOCKADDR_IN servAddr;

 if(argc != 3)
 {
  printf("Usage : %s <IP> <port> \n" , argv[0]);
  exit(1);
 }

 //Load WinSocket 2.2 DLL
 if(WSAStartup(MAKEWORD(2,2) , &wsaData) != 0)
  ErrorHandling("WSAStartup() error!");

 //서버 접속을 위한 소켓 생성
 hSocket = socket(PF_INET , SOCK_STREAM, 0);
 if(hSocket == INVALID_SOCKET)
  ErrorHandling("hSocketet() error!");

 memset(&servAddr , 0 , sizeof(servAddr));
 servAddr.sin_family  = AF_INET;
 servAddr.sin_addr.s_addr= inet_addr(argv[1]);
 servAddr.sin_port  = htons(atoi(argv[2]));

 //서버로 연결 요청
 if( connect(hSocket , (SOCKADDR*)&servAddr , sizeof(servAddr))
                                                                         == SOCKET_ERROR )
  ErrorHandling("connect() error!");

 //데이터 수신
 strLen = recv(hSocket , message , sizeof(message)-1 , 0);

 if(strLen==-1)
  ErrorHandling("read() error!");
 message[strLen]=0;
 printf("Message from server : %s\n" , message);

 //연결 종료
 closesocket(hSocket);
 WSACleanup();
 return 0;
}

void ErrorHandling(char* message)
{
 fputs(message , stderr);
 fputc('\n' , stderr);
 exit(1);
}

Posted by 갑빠돌격기

댓글을 달아 주세요

/************************************************************************
helloworld_server_win.c
 Written by SW.YOON
  참고 : TCP/IP 소켓 프로그래밍 / 윤성우 | 저

- 컴파일전 반드시 WS2_32.lib 라이브러리를 링크시켜야 한다.
- argument값으로 <포트번호> 가 필요하다.
************************************************************************/


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>

void ErrorHandling(char *message);

int main(int argc , char **argv)
{
 WSADATA        wsaData;
 SOCKET          hServSock;
 SOCKET          hClntSock;
 SOCKADDR_IN  servAddr;
 SOCKADDR_IN  clntAddr;
 int szClntAddr;

 char message[] = "Hello World\n";

 if(argc!=2)
 {
  printf("Usage : %s <port>\n" , argv[0]);
  exit(1);
 }

 // Load Winsock 2.2 DLL
 if(WSAStartup(MAKEWORD(2,2) , &wsaData) != 0)
  ErrorHandling("WSAStartup() error!");

 //서버 소켓 생성
 hServSock = socket(PF_INET , SOCK_STREAM , 0);
 if(hServSock == INVALID_SOCKET)
  ErrorHandling("socket() error!");

//sockaddr_in 구조체
 memset(&servAddr , 0 , sizeof(servAddr));
 servAddr.sin_family         = AF_INET;                 //주소체계(address_family)
 servAddr.sin_addr.s_addr = htonl(INADDR_ANY);  //32bit IPv4 주소
 servAddr.sin_port           = htons(atoi(argv[1])); //16bit TCP/UDP port
 //servAddr.sin_zero 는 특별한 의미없는 단순한 채워주기(padding)위한 멤버

 //소켓에 주소 할당
 if(bind(hServSock ,(SOCKADDR*)&servAddr,sizeof(servAddr))
                                                                        ==SOCKET_ERROR)
  ErrorHandling("bind() error");

 //연결요청 대기상태
 if(listen(hServSock , 5) == SOCKET_ERROR)
  ErrorHandling("listen() error");

 //연결 요청 수락
 szClntAddr = sizeof(clntAddr);
 hClntSock = accept(hServSock , (SOCKADDR*)&clntAddr , &szClntAddr);

 if(hClntSock == INVALID_SOCKET)
  ErrorHandling("accept() error");

 //데이터 전송
 send(hClntSock , message , sizeof(message) , 0);

 //연결 종료
 closesocket(hClntSock);

 WSACleanup(hClntSock);
 return 0;
}

void ErrorHandling(char *message)
{
 fputs(message , stderr);
 fputc('\n' , stderr);
 exit(1);
}

Posted by 갑빠돌격기

댓글을 달아 주세요