使用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);
}
复制代码

 

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

   

 

 

源码:下载

相关文章
|
网络安全 开发工具 git
|
JSON Rust 区块链
理解Rust的Result/Option/unwrap/?
我在学习Rust时,注意到有4个概念经常放到一起讨论:Result、Option、unwapr和?操作符。本文记录了我对这4个Rust概念的思考,这个思考过程帮助我理解并学会了如何写出更地道的Rust代码。
2127 0
|
9月前
|
缓存 JSON JavaScript
30分钟搞懂Rollup+Typescript工程构建(一)
最近在研究一个ngptcommit命令行工具,然后想通过Rollup+Typescript去编译的时候,发现对Rollup和Typescript的编译配置有点陌生,所以希望通过本文能够对其有个系统的认知。
146 0
|
11月前
|
并行计算 PyTorch TensorFlow
Win10系统下使用anaconda在虚拟环境下安装CUDA及CUDNN
以管理员身份打开Anaconda Prompt,输入下列命令查看conda目前支持的cudatoolkit版本。(注cudatoolkit也是cuda)
926 0
|
12月前
|
Java API Android开发
Android C++系列:访问Assets 文件夹.md
assets目录是Android的一种特殊目录,用于放置APP所需的固定文件,且该文件被打包到APK中时,不会被编码到二进制文件。 Android还存在一种放置在res下的raw目录,该目录与assets目录不同。
273 0
Flutter 底部导航栏BottomNavigationBar,并关联PageView实现滑动切换
Flutter 底部导航栏BottomNavigationBar,并关联PageView实现滑动切换
308 0
|
开发工具 Android开发 iOS开发
如何使用 Draggable 和 DragTarget 在 Flutter 中创建拖放 UI 元素?
如何使用 Draggable 和 DragTarget 在 Flutter 中创建拖放 UI 元素?
342 0
|
Windows 容器
一款简单的缩放拖拽图片控件
本文介绍一个针对 .NET 桌面应用程序的独立图片缩放拖拽显示控件 [SQPhoto](https://www.nuget.org/packages/SQPhoto/)。
144 0
一款简单的缩放拖拽图片控件
|
C++
MFC combo box 下拉框 快速使用
快速使用MFC combobox 的简单功能,本人博客,csdn搬运。
224 0
|
IDE 开发工具 C++
VS Code折腾记 - (2) 快捷键大全,没有更全
VSCode的快捷键继承了一些IDE风格,有VS Studio的身影,也有Emacs的身影, 简言之,内置快捷键玩熟了,效率提高不是一点两点。
223 0