ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 소켓과 MFC를 이용한 채팅 프로그램 개발하기 - 클라이언트편
    Windows 프로그래밍 2019. 3. 6. 18:07
    서버편 보고오기

    지난 서버편에 이은 클라이언트 개발 편이다.

    클라이언트에서는 서버와 달리 소켓 통신을 위해선 하나의 클래스만 있으면 된다.


    서버에서처럼 CConnectSocket이라는 클래스를 CSocket 클래스를 기본 클래스로 받아 생성한다.

    코드는 짧고 쉽다.

    #include "stdafx.h" #include "CConnectSocket.h" #include "SocketClientDlg.h" CConnectSocket::CConnectSocket() { } CConnectSocket::~CConnectSocket() { } void CConnectSocket::OnClose(int nErrorCode) // 서버와의 연결이 종료되었을 때 { ShutDown(); Close(); CSocket::OnClose(nErrorCode); AfxMessageBox(_T("ERROR:Disconnected from server!")); ::PostQuitMessage(0); } void CConnectSocket::OnReceive(int nErrorCode) // 소켓에 데이터가 들어왔을 때 { TCHAR szBuffer[1024]; ::ZeroMemory(szBuffer, sizeof(szBuffer)); if (Receive(szBuffer, sizeof(szBuffer)) > 0) { // 메시자를 받고


    CSocketClientDlg* pMain = (CSocketClientDlg*)AfxGetMainWnd(); int cnt = pMain->m_List.GetCount(); CString originText = szBuffer; CString RecName = pMain->name; RecName = L"[" + RecName + L"]:"; if (originText.Find(RecName) != -1) { // 메시지 발신자가 자신이면 originText = L"★ " + originText; // 메시지 앞에 별 표시하기 } else { originText = L" " + originText; // 아니면 공백 표시하기 } pMain->m_List.InsertString(cnt, originText); // 채팅처럼 보이도록 리스트에 추가 pMain->checknew = 1; } CSocket::OnReceive(nErrorCode); }

    이게 소켓을 통해 데이터를 받아 출력하는 CConnectSocket 클래스의 소스코드이다.

    그럼 이제 사용자의 이름을 설정하는 CAlias 클래스를 살펴보자.


    CAlias는 아래와 같은 Dialog를 생성하고 이 Dialog를 컨트롤하기 위해 추가한 클래스이다.


    void CAlias::OnBnClickedAlias() // 별명 설정 버튼 클릭 { CString str; CString alias = L"alias:"; GetDlgItemText(IDC_EDIT1, str); // EDIT 컨트롤에 있는 값을 가져와서 ((CSocketClientDlg *)GetParent())->name = str; str = alias + str; ((CSocketClientDlg *)GetParent())->m_Socket.Send((LPVOID)(LPCTSTR)str, str.GetLength() * 2);

    // alias:이름 의 형식으로 서버에 전송한다

    // 그럼 서버는 이 형식으로 온 메시지는 이름설정 용이란걸 알고 이름을 저장한다 ::SendMessage(this->m_hWnd, WM_CLOSE, NULL, NULL); // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다. } BOOL CAlias::PreTranslateMessage(MSG* pMsg) { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. if (pMsg->message == WM_KEYDOWN) { if (pMsg->wParam == VK_RETURN) { // Enter 키 지원용 OnBnClickedAlias(); return true; } } return CDialogEx::PreTranslateMessage(pMsg); }

    그럼 이제 메인 다이얼로그를 알아보자.

    메인 다이얼로그는 소켓을 생성하고 연결하는 등 기초적인 작업과 메시지를 보내는 작업 등을 담당한다.

    //////////////////////////////////////////////////////////// OnInitDialog 함수에서 CButton *button1 = (CButton*)GetDlgItem(IDOK); CButton *button2 = (CButton*)GetDlgItem(IDCANCEL); button1->DestroyWindow(); button2->DestroyWindow(); SetTimer(1, 100, NULL); // 타이머 시작 m_Socket.Create(); // 소켓 생성 if (m_Socket.Connect(_T("127.0.0.1"), 21000) == FALSE) { AfxMessageBox(_T("ERROR : Failed to connect Server")); PostQuitMessage(0); return FALSE; } // 소켓 Localhost에 연결 (내부망에서 다른 컴퓨터와 할 시 자신의 ip주소 입력)

    CAlias dialog1 = new CAlias(); dialog1.DoModal(); //////////////////////////////////////////////////////////////

    void CSocketClientDlg::OnBnClickedButton1() // 전송 버튼 눌렀을 때 { checknew = 0; CString str; UpdateData(TRUE); GetDlgItemText(IDC_INPUT, str); m_Socket.Send((LPVOID)(LPCTSTR)str, str.GetLength() * 2); // 전송^^ str.Format(_T("")); SetDlgItemText(IDC_INPUT, str); UpdateData(FALSE); // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다. } void CSocketClientDlg::OnBnClickedButton2() // 별명 설정 버튼 눌렀을 때 { CAlias dialog1 = new CAlias(); dialog1.DoModal(); // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다. } void CSocketClientDlg::OnTimer(UINT_PTR nIDEvent) { if (checknew == 1) { int line = m_List.GetCount(); // 추가한 갯수를 얻어옴 m_List.SetTopIndex(line - 1); // 얻어온 갯수로 스크롤 시킴 checknew = 0; } // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다. CDialogEx::OnTimer(nIDEvent); } // ListBox에 채팅을 표시하기 때문에 새 채팅이 들어오면 ListBox 스크롤을 내리기 위해 사용

    BOOL CSocketClientDlg::PreTranslateMessage(MSG* pMsg) { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. if (pMsg->message == WM_KEYDOWN) { if (pMsg->wParam == VK_RETURN) { // Enter 키 지원용 OnBnClickedButton1(); return true; } } return CDialogEx::PreTranslateMessage(pMsg); }

    여기까지가 소켓을 이용한 채팅 프로그램 개발이었다. 서버와 클라이언트 EXE는 첨부파일에 추가해 놓겠다.


    SocketClient.exe

    SocketServer.exe


    댓글

Designed by Tistory.