PROGRAMMING/MFC(C++)

[0407수업] 소켓실습

마마필로 2011. 4. 7. 00:52

소켓실습을 위한 프로젝트 만들기(프로젝트이름: 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에서 나눠서 함.