Posted by 마마필로 :

[0412수업]

2011. 4. 12. 00:56 from PROGRAMMING/MFC(C++)

파일입출력

시리얼 통신 구문 대치

 

Network: 간섭이 존재하는 통신

케이블통신: 간섭이 없는 통신

 

■ 파일입출력

 

1. 새프로젝트-MFC응용프로그램-대화상자 생성하여, 도구상자에서 버튼 3개 추가

2. 버튼 속성 변경

2.1 Caption 변경

Button1 → FILE OPEN

Button1 → FILE READ

Button1 → Read from CArchive

3.버튼을 클릭했을 때 처리할 이벤트 처리함수 만들기

해당 버튼 더블클릭하면 Dlg클래스(Dlg.cpp)에 'void CFILEIODlg::OnBnClickedButton1()'가 자동 등록

메시지 맵(Dlg.h)에도 이벤트 핸들러 함수 3개가 선언됨

 

4. 이벤트 핸들러에 코드 추가

4.1 OnBnClickedButton1()함수에 코드 추가

 

아카이브 클래스


Posted by 마마필로 :

■ 버튼에 이미지 입히기

 

1. 배경으로 쓰고자 하는 비트맵(bitmap)이미지 추가

2. 프로젝트의 rec폴더에 추가

3. 프로젝트-리소스뷰-리소스추가: res폴더에서 준비한 비트맵이미지 추가(ID수정)

4. 이미지를 넣을 버튼의 속성에서  Owner Draw를 true로 변경

5. 버튼에 변수 추가(변수형식: CBitmapButton으로 수정, 변수이름주기 → ex.)m_btnBmp)

6. Dlg클래스 cpp파일 → OnIntDialog()함수에 코드 추가

 

 m_btnBmp.LoadBitmaps(IDB_BITMAP_TEST1, IDB_BITMAP_TEST2, IDB_BITMAP_TEST3, IDB_BITMAP_TEST4);// 버튼에 이미지 입힙
 m_btnBmp.SizeToContent(); // 이미지를 버튼의 크기에 맞게 자동조절

 

→ m_btnBmp(정해준 변수이름)

→ LoadBitmaps(기본, 눌렀을때, 포커스가 올라왔을 때, 비활성화)

 

 

■ 대화상자 배경 이미지 넣기

 

1. 배경으로 쓰고자 하는 비트맵(bitmap)이미지 추가

2. 프로젝트의 rec폴더에 추가

3. 프로젝트-리소스뷰-리소스추가: res폴더에서 준비한 비트맵이미지 추가(ID수정)

4. Dialog창(***.rc)의 도구상자에서 Picture Control 추가

5. Picture Control의 속성에서 Type을 Bitmap으로 수정(ID수정)

6. Picture Control 아이콘에서 오른쪽클릭하여 변수 추가(변수이름주기 → ex.)m_imgBg)

7. Dlg클래스 cpp파일→ OnIntDialog()함수에 코드 추가

 

 HBITMAP hBit=LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_BG));

 m_imgBg.SetBitmap(hBit);
 
 CRect rt;
 GetClientRect(&rt);
 m_imgBg.SetWindowPos(NULL,0,0,rt.Width(),rt.Height(),SWP_SHOWWINDOW);


 
 
어제 소켓통신 이어서.....

 

접속 요청시

'IP입력'과 'local host'입력의 차이

IP입력시 IP를 찾기 위해 실제 라우터를 거쳐야 한다.

라우팅 테이블에 IP가 없으면 밖으로 나가지 못함

 

로컬 호스트의 경우 내 PC안의 IP만 검사하여

내 PC로만 통신을 하겠다고 명령하는 것

 

'임계영역'의 이해 要...

 

동기식/비동기식을 결정하는것은 프로그래머이지 소켓이 아니다.

 

버퍼의 용도

비주기적으로 데이터가 들어오면서 데이터가 몰려서 한꺼번에 다 받을 수 없는 경우를 대비해 버퍼공간에 데이터 저장.

(직접 수신하지 않고 중간에 빈 공간(버퍼)을 만들어 데이터를 모아두는 것)

그 후에 serialization(직렬화, 데이터를 일련화 시킴) 하여 처리함.

*1024바이트 이상이면 메모리에 버퍼를 만들 수 없음

→ 비동기 통신에서 가장 중요한 객체가 버퍼와 파일

→ 1024바이트 이상이 되면 파일버퍼를 사용해야 함

 

★ 데이터동기화/동기식통신/비동기식통신


'PROGRAMMING > MFC(C++)' 카테고리의 다른 글

[스크랩] bitmap 강의 내용 정리  (0) 2011.04.14
[0412수업]  (0) 2011.04.12
[0411수업] TCP/IP 소켓 프로그래밍  (0) 2011.04.11
[0408수업] 소켓통신 보충  (0) 2011.04.08
[0407수업] 소켓실습  (0) 2011.04.07
Posted by 마마필로 :

TCP/IP 소켓 프로그래밍은 아래의 세가지 함수로 시작한다.

 

Create(): 소켓을 생성하는 함수

Close(): 소켓을 닫는 함수

OnClose(): 소켓에 연결된 다른 소켓을 닫을 때 사용

 

Accept(): 클라이언트 소켓과 ChatServer의 OS소켓을 연결

Onaccept():

→ OnAccept안에 Accpet가 있어서 실제 요청이 일어남.

 


'PROGRAMMING > MFC(C++)' 카테고리의 다른 글

[0412수업]  (0) 2011.04.12
[0412수업] 버튼/대화상자에 이미지 넣기  (0) 2011.04.12
[0408수업] 소켓통신 보충  (0) 2011.04.08
[0407수업] 소켓실습  (0) 2011.04.07
[0407수업] 소켓의 이해  (0) 2011.04.07
Posted by 마마필로 :

//1바이트를 2바이트로 바꾸려면

char a = 'x';

TCHAR b = (TCHAR)a;

//TCHAR b = (TCHAR)'x';

→ sizeof(b);  // 실제 2바이트인지 크기 확인

 

//2바이트를 1바이트 char로 바꾸려면

TCHAR b;

strcpy ("%s", b);


Posted by 마마필로 :

소켓실습을 위한 프로젝트 만들기(프로젝트이름: CChatServer)

 

1. MFC클래스 추가(클래스이름: CSocServer, 기본클래스: CSocket)-연결을 담당하는 클래스

 

1.1 CChatServerDlg클래스가 CSocServer클래스를 이용할 수 있게 하기

 

//////////////////////////////////////////////////////////////////////////////////

//////

//////    다른 클래스의 데이터 받아 이용하려면,

//////

//////    1. 헤더파일 추가

//////    이용하려는 클래스에서 이용할 클래스의 헤퍼파일을 #include로 추가해주고,

//////

//////    2. 객체 생성

//////    같은 곳에 객체를 만들어 준다.(동적할당)

//////

//////////////////////////////////////////////////////////////////////////////////

 

ChatServerDlg.h에 #include "SocServer.h" 추가

CSocServer.h에서 속성-재정의 OnAccept // 소켓함수 재정의 OnAccept: 클라리언트로 부터 오는 접속 요청을 처리하는 함수

CSocServer.h에 Accept(); 추가

CSocServer.h에 SendMessage(m_hWnd, UM_ACCEPT, 0, 0); 추가

 

2. CSocket클래스 에서도 CCharServerDlg클래스를 이용할 수 있게 하기위해

윈도우 핸들값을 가져온다.

SocServer.cpp에

void CSocServer::InitHwnd()
{
 m_hWnd = hWnd;
};

ChatServerDlg.cpp의 메시지맵에 On_MESSAGE(UM_ACCEPT, ONAccept) 등록

ChatServerDlg.h에 afx_msg LPARAM OnAccept(UINT wPara, LPARAM lParam); 등록

 

stdafx.h의 상단에 #define UM_ACCEPT WM_USER+1 추가

 

 

3. MFC클래스 추가(클래스이름: CSocCom, 기본클래스: CSocket)

-데이터 송수신 담당(소켓서버는 연결 담당)

 

3.1 ChatServerDlg.h에 CSocCom m_socCom; 추가

3.2 SocCom.h에

public:
 HWND m_hWnd;
 void InitHwnd(HWND hWnd);추가

3.3 ChatServerDlg.h에 #include "SocCom.h" 추가

3.4 SocCom.cpp에,

void CSocCom::InitHwnd()
{
 m_hWnd = hWnd;
};

 

4. SocCom.cpp에서 OnReceive 함수 재정의

SendMessage(m_hWnd, UM_RECEIVE, 0,0); // 클라이언트 데이터가 도착했다는 것을 알려준다.

 

5. stdafx.h에  #define  UM_RECERVE WM_USER+2 추가

 

// 기본셋팅

 

이제 프로그램 작성.

 

1. 소켓 생성

ChatServerDlg.cpp의 OnInitDialog()함수에서 소켓을 만들어 준다.

 m_socCom = NULL;
 m_socServer.Create(8000);   // 소켓을 생성(포트번호 8000번)

 m_socServer.Listen();  // 클라이언트가 접속해오길 기다린다(스레드)

 m_socServer.InitHwnd(this->m_hWnd);  //소켓클래스와 메인 윈도우를 연결

(자기자신의 클래스에서(this) m_hWnd핸들을 socServer에서 가져오는 것??)

 

포트번호: 데이터 통신을 하기 위한 게이트. 상대방도 포트번호가 같아야 통신이 가능함. 양쪽이 같게 세팅해야 함.

 

2. 객체 바인딩

2.1 ChatServerDlg.cpp에

LPARAM CChatServerDlg::OnAccept(UNIT wParam, LPARAM lParam)
{
 // 클라이언트에서 접속요청이 왔을 때
 m_strStatus = "접속성공";
}

 

2.2 ChatServerDlg.h에 (아래 세줄 추가)

public:
 CSocServer m_socServer;
 CSocCom m_socCom;

 CString m_strSend;
 CString m_strStatus;
 CListBox m_list;

 

2.3 다시 ChatServerDlg.cpp에 다음과 같이 작성한다.

LPARAM CChatServerDlg::OnAccept(UNIT wParam, LPARAM lParam)

{
      // 클라이언트에서 접속요청이 왔을 때
      m_strStatus = "접속성공";
      // 통신용소켓을 생성한다.
      m_socCom = new CSocCom;
      //서버소켓과 통신소켓을 각각 연결한다.
      m_socCom = m_socServer_GetAcceptSocCom();
      m_socCom->InitHwnd(this->m_hWnd);

      m_socCom->Send("접속성공!!!", 256);
 
      UpdateData(FALSE);
      return TRUE;
}

 

2.4 SocServer.h에 GetAcceptSocCom()함수 선언

CSocCom* GetAcceptSocCom();

 

2.5 SocServer.cpp에서 구현

CSocCom*CSocServer::GetAcceptSocCom()
{
 return &m_socCom;
}

2.6 ChatServerDlg.h에 afx_msg LPARAM OnReceive(UINT wParam, LPARAM lParam); 추가

 

2.7 ChatServerDlg.cpp에서 메시지 처리 함수 작성

LPARAM CChatServerDlg::OnReceive(UNIT wParam, LPARAM lParam)
{
      char pTmp(256);
      CString strTmp;
      memset(pTmp, '\0', 256);

 

      m_socCom->Receive(pTmp,256);
      strTmp.Format("%s",pTmp);  //버퍼에 메시지 저장

 

      int i = m_listGetCount();
      m_list.InsertString(i, srtTmp); //리스트박스에 출력


      return TRUE;
}

 

2.8 ChatServerDlg.cpp에서 메시지맵에 추가

ON_MESSAGE(UM_RECEIVE, OnReceive)

 

 

2.9 CSocCom과 CSocServer간 통신이 안되는 문제점을 해결하기 위해

SocServer.cpp에 Accept()함수의 매개변수 추가. Accept(m_socCom);

SocServer.h에 선언 CSocCom m_socCom;

 

3. SendButton 더블클릭하여 아래 코드 추가

void CChatServerDlg::OnBnClickedButtonSend()
{
     UpdateData(TRUE);
     char pTmp[256];
     CString strTmp;
     // pTmp에 전송할 데이터를 담는다.
     

     memset(pTmp, '\0', 256);
     strcpy(pTmp, m_strSend); //전송

    

     m_socCom->Send(pTmp, 256);

     //전송한 데이터도 리스트박스에 보여준다.
     

     strTmp.Format("%s", pTmp);
     int i = m_list.GetCount();
     m_list.InsertString(i, strTmp);
}

 

// 이후과정은 못적음........



OnReceive()함수가 실행되는 시점

→ 파라미터 값을 보면 알 수 있다.

 

OnCreate()함수가 실행되는 시점

→ UM_RECEIVE메시지가 메시지 큐에 쌓이면 실행됨

 

실제 화면출력만 ChatServerDlg.cpp에서 하고,

신호를 받고 보내고 메시지를 보내고 받는것(실제 처리)은 SocServer와 SocCom에서 나눠서 함.


Posted by 마마필로 :

■ 소켓

 

기계장치를 다룰 때는 모두 OS를 통하게 된다. OS는 기계장치를 직접적으로 제어할 수 있는 소프트웨어라고 볼 수 있다.

고급언어 → 사람이 알아보기 쉬운 언어, 메모리에 올라가 있는 데이터를 다루는 일 밖에 할 수 있는 일이 없다.

데이터 올리기, 내리기, 가공하는 것만 고급언어로 가능하다.

프로그래밍 언어에서는 실제로 메모리밖에 다룰 수 있는게 없다.

 

cpu안에 짜 놓은 프로그램을 instruction set(=명령어 세트, core)라고 한다.

이 명령어들이 하는 일 역시, 메모리와의 작업만 가능 하다. 메모리에 데어터를 넣고 빼는 일 같은 것.

메모리에 저장되어 있는 함수를 빼내와서 core에서 돌린다.

하지만 이때는 함수라고 표현하지 않는다.

c언어와 같은 고급언어로 작성된 것이 컴파일되어 메모리로 올라가면 이미 함수가 아니며,

그것을 cpu의 명령어들이 가지고 와서 돌린다. 이것이 스레드이다.

cpu에서 처리한 결과를 다시 메모리에 올리고, 랭귀지(c언어, c#, java등)가 다시 가져가게 되는 것이다.

이런 과정을 거쳐 통신을 하게 되는 것이다.

 

고급언어(C, C#, JAVA...) ↔ 메모리 ↔ CPU

 

콘솔프로그램-키보드에서 올라오는 데이터를 버퍼라는 메모리공간을 사용하여 데이터 이용가능함(버터에 데이터를 넣었다 꺼냄)

파일-fopen함수 이용시 FILE구조체를 메모리에 올려놓은 후 포인터로 가리켜 사용

직렬통신-DCB

비트맵-RGB칼라 구조체에 저장했다 메모리에 올려서 사용

→ 함수의 이름만 다를 뿐 모두 메모리 공간을 이용해야만 데이터를 사용할 수 있다.

 

꼭 실제 데이터가 메모리에 올라가야 하는것은 아니지만 모두 메모리 공간을 거쳐야 이용가능하다.

(데이터가 너무 클 경우 포인터 등을 이용할 수 있다.)

메모리에 올라가 있는 데이터가 바로 소켓!

 

소켓을 다룬다는것은 실데이터(전송하거나 전송받는)와 실데이터와 함께 전송되어지는 메타데이터를 다룬다는 것이다.

이때 함수는 내가 만들거나 OS에서 제공한 것을 사용 가능하다. 하지만 실제로 직접 함수를 만든다는 것은 힘들다.

내가 함수를 만든다는것은 TCP/IP 프로토콜을 만든다는 것과 같다.

TCP/IP 프로토콜은 드라이버를 만들어줘야 하고 그것을 위해서는 C언어로만은 안되기 때문에,

OS가 만들어놓은 함수와 초기화 해 놓은 소켓구조체(구조체라고 하기엔 너무 크기 때문에 실제 구조체라고도 잘 안함)를 우리는 사용한다.

그래서 TCP/IP 구조체 프로그래밍이라고 하지 않고 '소켓'이라고 한다.

 

CSocket과 CAsyncSocket의 차이는  가지고 있는 메타정보가 다르다는 것이다.

실 데이터는 차이가 없고 어떤 식으로 통신을 하겠느냐는 것. 각각 동기식, 비동기식 소켓.

 



소켓(Socket)-TCP/IP 프로토콜(운영체제에 설치되어 있는 소프트웨어)과

현재 내가 만들고 있는 프로그램(예를 들면 메신저와 같은)을 중간에서 연결해주는 구조체와 함수의 집합

 

CSocket - 구조체, 함수...

CAsyncSocket - 구조체, 함수...

 

CAsyncSocket - Object클래스로부터 직접 상속 받은 최상위 클래스 중 하나이다.

CSocket - CAsyncSocket을 상속받아서 만든 클래스이다.

 

전자는 소켓 프로그래밍에 필요한 내용을 제공하는 기본클래스(Base Class)로서, 비동기식으로 동작하며,

후자는 전자를 상속받아 좀 더 많은 기능을 편리하게 제공한다.

 

동기식, 비동기식 동작의 차이

(동기식 입/출력, 동기화 프로그래밍과는 다른 얘기. 네트웍에서 동기식/비동기식으로 동작 한다는 것.)

동기식이란, 하나의 작업이 끝나기 전까지는 다른 작업을 할 수 없는 동작방식.

CSocket(동기식 동작방식)은 10MB의 파일을 전송하기 위해서 상당한 시간이 소요되는데도 불구하고,

응용프로그램은 전송행위가 끝날때까지 아무것도 하지 못한 채 기다려야 한다는 의미이다.

 

비동기식은 동기식의 역으로 생각하면 된다. 즉, 현재 전송중인 파일이 있음에도 또다른 파일을 전송하는 등의 작업이 가능하다.

 

TCP/IP 프로토콜  ↔ CSocket ↔ P/G

 

실제 TCP/IP 프로그래밍을 할때는 통신관련 WinAPI에 수많은 함수들이 존재하므로 WinAPI를 프로그램에서 다이렉트로 불러서 이용한다.

CSocket에서 제공하는 함수는 종류가 얼마안되므로 실제 업무에서 MFC 클래스 중 CSocket은 사용빈도가 낮다.

→ TCP/IP 프로그래밍 할 때 WinAPI를 사용.

Posted by 마마필로 :

1. mfc에서 윈도우 메시지를 처리하는 경로 (win api message driven 방식과 비교)

사용자 이벤트 발생(어떤 이벤트가 어디에 발생?)

 

메시지를 잘 지원하지 않는 클래스들의 특징

→ 화면에 잘 보여지지 않는 클래스들(어플리케이션이나 다큐먼트 클래스와 같은 것들)

→ 어떤 클래스를 상속받느냐에 따라 메시지 처리 여부가 결정됨

→ 그렇다면, 메시지를 처리할 수 없는 클래스의 용도는?

 

App클래스의 용도

App클래스 에서는 주로 어떤것을 작성?

→ 프로그램에 사용되는 환경변수 적용

→ 부모 윈도우 생성

 

View클래스와 같은 화면을 보여주는 클래스에서 환경변수를 사용하기 위해 App클래스의 환경변수를 가져오는 방법

→ 포인터로 가리킨다.

→ 참조호출

그렇다면, App클래스에 어떻게 선언이 되어있어야 가져다 쓰는 클래스에서 포인터나 참조호출이 가능할 것인가?

생각보다 사용하는 것보다 선언하는 방식이 어렵고 중요하다. 따라서 잘 가져다 쓸 수 있도록 선언을 잘 해야 한다.

abstact, public, static등의 키워드들 중 어떤 것을 이용해서 선언할지를 결정하는 기준은 무엇일까?

 

정적변수(static)는 변수내의 값을 공유

전역변수는 공간을 공유

 

MFC에서 연산만 하는 함수는 4개중 어느 클래스에 만드는 것이 좋을까.

→ 새로운 클래스를 만들어서 한다.

만약 기존의 클래스에 집어 넣으면 연산을 이용하기 위해 전체를 불러야 한다.

 

포인터를 쓰는 경우

→ 가져와야 할 데이터가 너무 클 경우

→ 데이터를 가져올 수 없을 때(ex. OS가 가지고 있는 데이터(DC 등))

 



WinForm에서 타 클래스 함수 호출하기

1. 클래스 추가

2, 추가된 클래스에 변수 선언 및 초기화

namespace CSharp
{
    class Class1
    {
        public int left;
        public int top;
        public int right;
        public int bottom;        // 변수 선언

 

        Class1()
        {
            left = 100;
            top = 200;
            right = 300;
            bottom = 400;        // 초기화
        }
    }

3. 기존 클래스에 객체 생성하면, 새로만든 클래스의 데이터를 쓸 수 있다.

Class1 csClass = new Class1();

 



클래스 추가하여 함수생성, int의 합을 double형으로 화면에 출력

mfc나 winapi의 클래스는 전역클래스의 개념

 

함수를 제공받을 수 있는 곳

C표준라이브러리

win api

mfc클래스


Posted by 마마필로 :

1. 기본 윈도우에 사각형 만들기, 문자 출력하기

 

 

2. 클래스 추가(자식 클래스)

2.1  뷰 클래스 헤더파일에 CWnd객체 생성

// 작업입니다.
public:
 CWnd m_child;           // 관례적으로 객체이름 앞에 'm_'를 붙여준다.(member라는 의미)

 

 

2.2_1 view.cpp에서 OnCreate 메시지 생성

 

 

 

2.2_2 view.cpp에서 OnPaint 메시지 생성

void CTextOutDemoView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    m_wndChild.Create(TEXT("STATIC"), TEXT("DEMO"), WS_CHILD|WS_VISIBLE|WS_BORDER, CRect(100, 100, 200, 300), this, 1);

 

    return 0;
}

 

→ 그린것이 아니라 윈도우를 생성한 것이기 때문에 OnCreate메시지 에서도 무효화되지 않는다.


Posted by 마마필로 :

■ 윈도우 기반의 응용프로그램을 만들 수 있는 세가지 개발 환경

1. CPP-MFC

2. Win32(WinAPI)-SDK

3. CS-WinForm

 

그밖에,

RAD Tool(Visual Basic, Delphi, Power Builder 등)이 있으나 기능이 제한적임.

 

■ 함수 이름 짓기

초기화..INITIALIZE...(INITINSTANCE..)

메세지루프..RUN...

메시지처리..HANDLE...(or) 처리하는 행동자체를 이름으로 쓰기도 함(LBUTTONDOWN과 같이)

→ 이름만으로 예측가능한, 실제 동작을 반영하여 짓는다.

 

■ 코드 비교

1. CSWINFORM (C#)

1.1 InitializeComponent() 

private void InitializeComponent()        //윈도우 사양 결정, 가장 먼저 실행되어야 함

        {
            this.SuspendLayout();
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(309, 282);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

1.2

namespace CSWINFORM
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]

 // STA(Single Thread Apartment): 애플리케이션 스레드의 모델을 단일 스레드로 지정하는 속성. 다중 스레드를 사용하지 않는다는 것을 의미하기도 한다. 메시지 루프가 돌려면 스레드가 필요.
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());        // C#에서 메시지 루프
        }
    }
}

 

내가 구현한적이 없는 함수가 실행될때는 정의로 이동하여 원형/요약 확인. 보다 더 정확한 사용을 보기 위해서는 msdn이용 한다.

 

2. CSDK

 

 

3. Mfc


Posted by 마마필로 :