SW 개발

[MFC] 간단프로젝트, 채팅프로그램 server , client

. . . 2012. 1. 31. 09:27
반응형
  • 이전에 테스트용으로 짰던 코드...
  • vs5.0 으로 짰던 pc용 프로그램입니다. 소스파일은 압축해서 올립니다.

잡담..

그냥 깔끔하게 예제가 제일좋다.

예제코드

예재코드 압축

Sock.zip

예제코드

MySocket.h

class CMySocket : public CAsyncSocket
{
// Attributes
public:

// Operations
public:
    CMySocket();
    virtual ~CMySocket();

// Overrides
public:
    void SetParent(CDialog* pWnd);

protected:
    virtual void OnSend(int nErrorCode);
    virtual void OnReceive(int nErrorCode);
    virtual void OnClose(int nErrorCode);
    virtual void OnConnect(int nErrorCode);
    virtual void OnAccept(int nErrorCode);
private:
    CDialog* m_pWnd;
};

MySocket.cpp

// MySocket.cpp : implementation file

#include "stdafx.h"
#include "Sock.h"
#include "MySocket.h"
#include "SockDlg.h"

CMySocket::CMySocket()
{
}

CMySocket::~CMySocket()
{
    Close();
}

void CMySocket::SetParent(CDialog *pWnd)
{
    // Set the member pointer
    m_pWnd = pWnd;
}

void CMySocket::OnAccept(int nErrorCode)
{
    // Were there any errors?
    if(nErrorCode == 0)
        // no, call the dialog's OnAceept fuction
        ( (CSockDlg*) m_pWnd)->OnAccept();
}

void CMySocket::OnConnect(int nErrorCode)
{
    if(nErrorCode == 0)
        // no, call the dialog's OnConnect fuction
        ( (CSockDlg*) m_pWnd)->OnConnect();
}

void CMySocket::OnClose(int nErrorCode)
{
    if(nErrorCode == 0)
        // no, call the dialog's OnClose fuction
        ( (CSockDlg*) m_pWnd)->OnClose();
}

void CMySocket::OnReceive(int nErrorCode)
{
    if(nErrorCode == 0)
        // no, call the dialog's OnReceivve fuction
        ( (CSockDlg*) m_pWnd)->OnReceive();
}

void CMySocket::OnSend(int nErrorCode)
{
    if(nErrorCode == 0)
        // no, call the dialog's OnSend fuction
        ( (CSockDlg*) m_pWnd)->OnSend();
}

SockDlg.h

// SockDlg.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CSockDlg dialog

class CSockDlg : public CDialog
{
// Construction
public:
    void OnClose();
    void OnReceive();
    void OnSend();
    void OnConnect();
    void OnAccept();
    CSockDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
    //{{AFX_DATA(CSockDlg)
    enum { IDD = IDD_SOCK_DIALOG };
    CListBox    m_ctlRecvd;
    CListBox    m_ctlSent;
    CButton m_ctlConnect;
    CString m_strMessage;
    CString m_strName;
    int     m_iPort;
    int     m_iType;
    //}}AFX_DATA

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CSockDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL

// Implementation
protected:
    HICON m_hIcon;

    // Generated message map functions
    //{{AFX_MSG(CSockDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnRType();
    afx_msg void OnBconnect();
    afx_msg void OnBsend();
    afx_msg void OnBclose();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    BOOL m_bConnected;
    CMySocket m_sConnectSocket;
    CMySocket m_sListenSocket;
};

SockDlg.cpp

// SockDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Sock.h"
#include "SockDlg.h"
#include "MySocket.h"

...
...

/////////////////////////////////////////////////////////////////////////////
// CSockDlg message handlers

BOOL CSockDlg::OnInitDialog()
{
...    
    // TODO: Add extra initialization here
    // Initialize the control variabls

    m_iType = 0;
    m_strName = "loopback";
    m_iPort = 4000;

    // Update the controls
    UpdateData(FALSE);

    // Set the socket dialog pointers
    m_sConnectSocket.SetParent(this);
    m_sListenSocket.SetParent(this);

    m_bConnected = FALSE;

    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSockDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialog::OnSysCommand(nID, lParam);
    }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSockDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSockDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

void CSockDlg::OnRType() 
{
    // TODO: Add your control notification handler code here
    // Sync the controls with the variables
    UpdateData(TRUE);

    // Which mode are we in?
    if(m_iType == 0) // Set the appropriate text on the button
        m_ctlConnect.SetWindowText("C&onnect");
    else
        m_ctlConnect.SetWindowText("&Listen");
}

void CSockDlg::OnBconnect() 
{
    // TODO: Add your control notification handler code here
    // Sync the variables with controls
    UpdateData(TRUE);

    // Disable the connection and type controls
    GetDlgItem(IDC_BCONNECT)->EnableWindow(FALSE);
    GetDlgItem(IDC_ESERVNAME)->EnableWindow(FALSE);
    GetDlgItem(IDC_ESERVPORT)->EnableWindow(FALSE);
    GetDlgItem(IDC_STATICNAME)->EnableWindow(FALSE);
    GetDlgItem(IDC_STATICPORT)->EnableWindow(FALSE);
    GetDlgItem(IDC_RCLIENT)->EnableWindow(FALSE);
    GetDlgItem(IDC_RSERVER)->EnableWindow(FALSE);
    GetDlgItem(IDC_STATICTYPE)->EnableWindow(FALSE);

    // Are we running as client of server?
    if(m_iType == 0)   // client
    {
        // Client, create a default socket
        m_sConnectSocket.Create();
        // Open the connection to the server
        m_sConnectSocket.Connect(m_strName, m_iPort);
    }
    else    // server
    {
        // Server, create a socket bound to the port specified
        m_sListenSocket.Create(m_iPort);
        // Listen for connection requests
        m_sListenSocket.Listen();
    }
}

void CSockDlg::OnAccept()
{
    if(m_bConnected)
    {
        // Create a rejection socket
        CAsyncSocket sRjctSock;

        // Create a message to send
        CString strMsg = "Too many connections, try again later.";

        // Accept usingthe rejection socket
        m_sListenSocket.Accept(sRjctSock);

        // Send the rejection message
        sRjctSock.Send(LPCTSTR(strMsg), strMsg.GetLength());

        // Close the socket
        sRjctSock.Close();
    }
    else
    {
        // Accept the connection request
        m_sListenSocket.Accept(m_sConnectSocket);

        // Enable the text and message controls
        GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
        GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
        GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
        m_bConnected = TRUE;
    }
}

void CSockDlg::OnConnect()
{
    // Enable the text and message controls
    GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
    GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
    GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
    GetDlgItem(IDC_BCLOSE)->EnableWindow(TRUE);
}

void CSockDlg::OnSend()
{

}

void CSockDlg::OnReceive()
{
    char* pBuf = new char[1025];
    int iBufSize = 1024;
    int iRcvd;
    CString strRecvd;

    // Receive the message
    iRcvd = m_sConnectSocket.Receive(pBuf, iBufSize);

    // Did we receive anything?
    if(iRcvd == SOCKET_ERROR)
    {
    }

    else

    {
        // Truncate the end of the message
        pBuf[iRcvd] = NULL;

        // Copy the message to a CString
        strRecvd = pBuf;

        // Add the message to the received list box
        m_ctlRecvd.AddString(strRecvd);

        // Sync the variables with the controls
        UpdateData(TRUE);
    }
}

void CSockDlg::OnClose()
{
    // Close the connected socket
    m_sConnectSocket.Close();

    // Disable the message sending controls
    GetDlgItem(IDC_EMSG)->EnableWindow(FALSE);
    GetDlgItem(IDC_BSEND)->EnableWindow(FALSE);
    GetDlgItem(IDC_STATICMSG)->EnableWindow(FALSE);
    GetDlgItem(IDC_BCLOSE)->EnableWindow(FALSE);

    // Are we running in Client mode?
    if(m_iType == 0)
    {
        // Yes, so enable the connection configuration controls
        GetDlgItem(IDC_BCONNECT)->EnableWindow(TRUE);
        GetDlgItem(IDC_ESERVNAME)->EnableWindow(TRUE);
        GetDlgItem(IDC_ESERVPORT)->EnableWindow(TRUE);
        GetDlgItem(IDC_STATICNAME)->EnableWindow(TRUE);
        GetDlgItem(IDC_STATICPORT)->EnableWindow(TRUE);
        GetDlgItem(IDC_RCLIENT)->EnableWindow(TRUE);
        GetDlgItem(IDC_RSERVER)->EnableWindow(TRUE);
        GetDlgItem(IDC_STATICTYPE)->EnableWindow(TRUE);
    }
}

void CSockDlg::OnBsend() 
{
    // TODO: Add your control notification handler code here
    int iLen;
    int iSent;

    // Sync the controls with the variables
    UpdateData(TRUE);

    // Is there a message to be sent?
    if(m_strMessage != "")
    {
        // Get the length of the message
        iLen = m_strMessage.GetLength();

        // Send the message
        iSent = m_sConnectSocket.Send(LPCSTR(m_strMessage), iLen);

        // Were we able to send it?
        if(iSent == SOCKET_ERROR)
        {
        }
        else
        {
            // Add the message to the list box.
            m_ctlSent.AddString(m_strMessage);
            // Sync the variables with the controls
            UpdateData(TRUE);
        }
    }
}

void CSockDlg::OnBclose() 
{
    // TODO: Add your control notification handler code here
    // Call the OnClose function
    m_bConnected = FALSE;
    OnClose();
}

끗.

반응형