C++/MFC

[MFC] 채팅 프로그램 - 클라이언트 (2/3)

balabala 2021. 8. 26. 14:59
728x90
SMALL
- 설명 - 
프로젝트 명 : ChatClient(대화 상자)
① CSocket 클래스 이용 : 동기식(블로킹)으로 동작
② 서버 클라이언트 1:1 통신
③ 해당 글은 클라이언트 채팅 프로그램 만드는 법 설명

 

1. MFC 애플리케이션 옵션 설정
애플리케이션 종류 : 대화 상자
[고급 기능] → [Windows 소켓] 활성화

그림1. MFC 애플리케이션 옵션 설정

 

2. 다이얼로그 디자인 및 ID

그림2. 클라이언트 프로그램 다이얼로그
그림3. 멤버변수 설정

 

3. CSocket 기반의 CSocCom MFC 클래스 생성
[프로젝트] → [클래스 마법사] → [클래스 추가] 버튼 옆의 ▼ 버튼 → [MFC 클래스] 선택 → 클래스 생성
CSocCom :   통신용 소켓

그림4. MFC 클래스 만드는 방법
그림5. CSocCom 클래스

4. CSocCom MFC 클래스에 가상 함수 추가
OnReceive(CSocCom) : 데이터가 도착했다는 것을 알려줌

그림6. OnRecieve 가상 함수 추가

 

5. CSocCom 클래스 작업
HWND m_hWnd : 메인 윈도우 핸들
Init() : 소켓 클래스와 메인 윈도우를 연결시킴
OnReceive() : 데이터가 도착했다는 것을 알려줌

그림7. SocCom.h 소스 코드

  • SocCom.h 소스 보기
더보기
#pragma once

// CSocCom 명령 대상
// 통신용 소켓
#include <afxsock.h>    // 소켓 클래스 사용 위해 include

#define UM_RECEIVE WM_USER+2

class CSocCom : public CSocket
{
public:
    CSocCom();
    virtual ~CSocCom();

    HWND m_hWnd;                                // 메인 윈도우 핸들
    void CSocCom::Init(HWND hWnd);                // 소켓 클래스와 메인 윈도우를 연결시킴    
    virtual void OnReceive(int nErrorCode);        // 데이터가 도착했다는 것을 알려줌
};
 
  • SocCom.cpp 소스 보기
더보기
// CSocCom 멤버 함수
// 소켓 클래스와 메인 윈도우를 연결시킴
void CSocCom::Init(HWND hWnd) {
    m_hWnd = hWnd;
}

// 데이터가 도착했다는 것을 알려주는 가상 함수
void CSocCom::OnReceive(int nErrorCode)
{
    // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
    SendMessage(m_hWnd, UM_RECEIVE, 0, 0);
    CSocket::OnReceive(nErrorCode);
}
 

 

6. ChatServerDlg에 통신용 소켓 선언 및 메시지 함수 추가
CSocCom m_socCom : 통신용 소켓
OnReceive() : 소켓 연결 이후 모든 통신을 해당 메시지 함수를 이용함.

그림8. 통신용 소켓 선언
그림9.&nbsp;ChatServerDlg.h 메시지 함수 추가
그림10. ChatServerDlg.cpp 메시지 함수 추가

  • OnReceive() 소스 보기
더보기
// 데이터를 보내는 것은 소켓 클래스의 멤버 함수인 Send를 이용
// 데이터를 받을 때는 통신 소켓 클래스에 오버라이딩한 OnReceive 메시지 함수를 사용
LPARAM CChatClientDlg::OnReceive(UINT wParam, LPARAM lParam) {
    // 접속된 곳에서 데이터가 도착했을 때
    char pTmp[256];
    CString strTmp;
    memset(pTmp, '\0', 256);

    // 데이터를 pTmp에 받는다.
    m_socCom.Receive(pTmp, 256);
    strTmp.Format("%s", pTmp);

    // 리스트박스에 보여준다.
    int i = m_list.GetCount();
    m_list.InsertString(i, strTmp);
    return TRUE;
}
 
SMALL
7. [접속] 및 [전송] 버튼 클릭 메시지 함수 작업
[접속] 버튼 클릭 시 서버에 접속 요청 보냄
[전송] 버튼 클릭 시 연결 된 서버에게 데이터 전송

그림11. [접속] 버튼 클릭 메시지 함수
그림12. [전송] 버튼 클릭 메시지 함수

  • 메시지 함수 소스 보기
더보기
// 서버에 접속 요청
// 소켓 클라이언트의 Create함수에서 인자가 있으면 서버로 인식하므로, 인자를 넘기지 않는다. 그러면 클라이언트로 판단해서 동작.
// Create로 소켓을 생성했다면 실제 접속은 Connect 함수를 이용
// 첫번째 인자를 이용해(m_strIP는 에디터 컨트롤과 연결된 멤버 변수) 접속할 곳의 IP 주소를 넘기며 두번째 인자를 통해 접속할 포트 번호를 지정
void CChatClientDlg::OnClickedButtonConnect()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    // 접속
    UpdateData(TRUE);
    m_socCom.Create();
    // IP 주소와 포트 번호를 지정
    m_socCom.Connect(m_strIP, 5000);
    m_socCom.Init(this->m_hWnd);
}

// [전송] 버튼을 클릭했을 때
void CChatClientDlg::OnClickedButtonSend()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    UpdateData(TRUE);
    char pTmp[256];
    CString strTmp;

    // pTmp에 전송할 데이터 입력
    memset(pTmp, '\0', 256);
    strcpy_s(pTmp, m_strSend);
    m_strSend = "";

    // 전송
    m_socCom.Send(pTmp, 256);

    // 전송한 데이터도 리스트박스에 보여준다.
    strTmp.Format("%s", pTmp);
    int i = m_list.GetCount();
    m_list.InsertString(i, strTmp);

    UpdateData(FALSE);
}
 

 

8. 실행 화면


관련 글
 

[MFC] 채팅 프로그램 - 서버 (1/3)

- 설명 - 프로젝트 명 : ChatServer(대화 상자) ① CSocket 클래스 이용 : 동기식(블로킹)으로 동작 ② 해당 글은 서버용 채팅 프로그램 만드는 법 설명 1. MFC 애플리케이션 옵션 설정 ① 애플리케이션 종

balabala.tistory.com

 

 

[MFC] 채팅 프로그램 - 다중접속(멀티) (3/3)

- 설명 - ① 1, 2번에서 설명한 Server와 Client를 수정 ② 설정에 따라 서버만 모든 클라이언트와 통신 가능하거나, 클라이언트도 같은 클라이언트끼리 통신 가능 1. Client : 다이얼로그 디자인 및 ID

balabala.tistory.com

 

728x90
LIST