zoukankan      html  css  js  c++  java
  • 使用CAsyncSocket总结

    最近想起CAsyncSocket这个类,记得很早以前用过,现在却想不起来怎么用了,翻了翻以前的代码又看了看msdn感觉这个类做简单的异步socket太简单了,几行代码就可以搞定,在此先做个总结。

    不管是客户端和服务端都要从CAsyncSocket这个类派生一个类来重载一系列Socket消息事件函数比如  CAsyncSocket::OnAccept  CAsyncSocket::OnReceive 等

    1.服务端

       1.1首先派生一个类用来监听

    class CListenSocket : public CAsyncSocket
    {
    public:
    public:
        CListenSocket();
        virtual ~CListenSocket(); 
        void SetListBox(CListBox * ListBox) {m_ListBox = ListBox;}         //这个ListBox是主窗口里面的一个客户端列表用来显示有几个客户端
        void SetListBoxMsg(CListBox * ListBox) {m_ListBoxMsg = ListBox;}   //这个ListBox是接收客户端消息的
    public:
        virtual void OnAccept(int nErrorCode);
        virtual void OnClose(int nErrorCode);
        CClientSocket * GetClientByIndex(int nIndex)  //返回一个已经连接的客户端用来给指定客户端发消息
        { 
            return m_ClientSocketList.GetAt(m_ClientSocketList.FindIndex(nIndex));
        }  
    private:
        CList<CClientSocket * > m_ClientSocketList;  //这里要维护一个已经连接的客户端列表,这样服务器可以指定向哪个服务器发消息
        CListBox * m_ListBox;
        CListBox * m_ListBoxMsg;
    };

       要响应监视类的Accept事件

    void CListenSocket::OnAccept(int nErrorCode)
    {
        // TODO: 在此添加专用代码和/或调用基类
        if (nErrorCode == 0)//如果成功
        {
            CClientSocket* pNewClientSocket = new CClientSocket(); //保存一个已经连接的客户端
            BOOL bAccept=Accept(*pNewClientSocket);
            if (bAccept)
            {
                m_ClientSocketList.AddTail(pNewClientSocket);
                pNewClientSocket->SetListBox(m_ListBoxMsg);
                CString SocketName;
                UINT len = 100;
                pNewClientSocket->GetSockName(SocketName,len);
                m_ListBox->AddString(SocketName);           //客户端列表里显示这个已经连接的客户端ip
            }
            else
            {
                DWORD dwErr = GetLastError();
                CString strErr;
                strErr.Format(_T("accept 错误码=%d"),dwErr);
                delete pNewClientSocket;
                AfxMessageBox(strErr);
            }
        }
        CAsyncSocket::OnAccept(nErrorCode);
    }

       已经连接客户端对象也是从CAsyncSocket派生来的、

      

    class CClientSocket : public CAsyncSocket
    {
    public:
        CClientSocket();
        virtual ~CClientSocket();
        virtual void OnReceive(int nErrorCode);
        virtual void OnClose(int nErrorCode);
        VOID SetListBox(CListBox * ListBox) {m_ListBox = ListBox;}
        CListBox * m_ListBox;
    private:
    };

      当服务端收到消息时要响应事件OnReceive

      

    void CClientSocket::OnReceive(int nErrorCode)
    {
        // TODO: 在此添加专用代码和/或调用基类
    
        if (nErrorCode == 0)
        {
            char szBuf[1024] = {0};
            INT nReceiveCounts = Receive((VOID*)szBuf,1024);
            if(m_ListBox != NULL)
                m_ListBox->AddString(szBuf);
    
        }
        
    
        CAsyncSocket::OnReceive(nErrorCode);
    }

       1.2 监听

       

    void CMfcSocketDlg::OnBnClickedButton1()
    {
        // TODO: 在此添加控件通知处理程序代码
        if(m_ListenSocket != NULL)
            return ;
        BOOL bInit = AfxSocketInit();
        if(!bInit)
        {
            AfxMessageBox(_T("socket 初始化失败 "));
            return ;
        }
        m_ListenSocket = new CListenSocket();
        BOOL bCreate = m_ListenSocket->Create(10101);
        if(!bCreate)
        {
            AfxMessageBox(_T("创建失败"));
            delete m_ListenSocket;
            m_ListenSocket = NULL;
        }
    
        BOOL bListen = m_ListenSocket->Listen();
        if(!bListen)
        {
            AfxMessageBox(_T("监听失败!"));
            delete m_ListenSocket;
            m_ListenSocket = NULL;
        }
        m_ListenSocket->SetListBox(&m_ListBoxClientList);  //客户端列表
        m_ListenSocket->SetListBoxMsg(&m_ListBoxRecMsg);   //已经接收的消息
    }

    2.客户端

      2.1 派生一个类用来作为客户端socket

       

    #include "afxsock.h"
    class CClientSocket :
        public CAsyncSocket
    {
    public:
        CClientSocket(void);
        virtual ~CClientSocket(void);
        
        virtual void OnReceive(int nErrorCode);
        virtual void OnClose(int nErrorCode);
        virtual  void OnConnect(int nErrorCode );
    
        void SetListBox(CListBox * ListBox) {m_ListBox = ListBox;}
        CListBox * m_ListBox;
    };

      想接收消息就要响应接收消息的事件

      

    void CClientSocket::OnReceive(int nErrorCode)
    {
        if(nErrorCode == 0)
        {
            CString szBuf;
            INT nReceiveCounts = Receive((VOID*)szBuf.GetBuffer(1000),1000);
            m_ListBox->AddString(szBuf);
        }
    }

      2.2 客户端对象的创建和连接 

      

    void CMfcSocketClientDlg::OnBnClickedButton1()
    {
        // TODO: 在此添加控件通知处理程序代码
        UpdateData(TRUE);
        BOOL bInit = AfxSocketInit();
        if(!bInit)
        {
            AfxMessageBox(_T("socket 初始化失败 "));
            return ;
        }
        if(m_ClientSocket == NULL)
        {
            m_ClientSocket = new CClientSocket;
            m_ClientSocket->Create();
        }
        else
        {
            m_ClientSocket->Close();
        }
        m_ClientSocket->Connect(m_Ip,m_Port);
        m_ClientSocket->SetListBox(&m_ListBox);
    }

    上个图片上源码供新手学习

       

    源码:下载

  • 相关阅读:
    Netty实战
    ObjectTools反射实例
    SpringBoot新增监听器Listener
    拦截器(Inteceptor),过滤器(Filter),切面(Aspect)处理HttpServiceReqeust请求
    Linux CentOS7.2下安装Redis && 配置Redis开机自启动
    JVM命令行工具&垃圾收集器&垃圾收集策略思维导图
    Redis总结
    Java自定义注解的实现
    反射实例
    系统管理员常用的Linux命令
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/3373248.html
Copyright © 2011-2022 走看看