Advertisement

mfc异步TCP Client通信向主线程发送接收消息

阅读量:

对于基于微软基础类库(MFC)的应用程序设计者而言,在开发一个异步TCP客户端程序时,若希望将接收的报文传输至主线程以便处理,则需要考虑通过线程间通信机制来实现这一过程。微软基础类库(MFC)为开发者提供了相应的机制,以确保能够在工作线程与主线程之间安全地传输报文。

步骤概述:

  1. 建立一个独立的异步TCP客户端进程:该进程专门用于接收数据流。
  2. 由主线程接收并处理来自客户端的数据:当TCP客户端完成接收到数据时(即调用Read方法),主框架会通过调用SendMessage函数向主线程传递这些信息。
  3. 在主线程中设置相应的回调函数来处理来自客户端的消息:主框架会根据接收到的数据内容(如字符串值或数值)动态地设置相应的回调函数来处理这些信息。

实现步骤

1. 创建异步TCP客户端线程

通过调用AfxBeginThread创建并开始一个工作线程来实现对TCP通信的支持。通过Windows的socket API或其他相关库函数来实现TCP通信的支持。

复制代码
    UINT ClientThread(LPVOID pParam)
    {
    CYourMainDlg* pDlg = (CYourMainDlg*)pParam;
    
    // 这里初始化你的socket并开始接收数据
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    // 配置服务器地址和端口
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(12345);  // 设置端口号
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  // 设置服务器IP
    
    // 连接到服务器
    connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
    
    char recvBuffer[1024];
    while (true)
    {
        // 接收数据
        int recvLen = recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
        if (recvLen > 0)
        {
            recvBuffer[recvLen] = '\0';  // 确保接收到的数据是字符串
            
            // 将接收到的数据通过PostMessage发送到主线程
            pDlg->PostMessage(WM_RECEIVE_DATA, (WPARAM)new CString(recvBuffer), 0);
        }
        else
        {
            // 处理错误或断开
            break;
        }
    }
    
    // 关闭socket
    closesocket(clientSocket);
    return 0;
    }
    
    
    AI生成项目cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/Xou2APtD0aqvSB7hlmcgIKWeUOr4.png)

在本例中,该线程被配置为一个后台工作线程,并负责与服务器建立通信以接收 incoming data。当该线程成功接收 data 时,默认会通过调用PostMessage方法将 received data传递给主程序流程。

2. 定义消息和消息处理函数

在Microsoft Windows API(MAPI)框架下(即MFC中),允许通过指定消息类型实现跨线程的消息传递机制被称为PostMessage。为此功能建议创建特定的消息格式以确保数据传输的准确性和可靠性,并为处理来自子线程的数据提供清晰的接口机制。

复制代码
    // 在CYourMainDlg类的头文件中,定义一个消息宏
    #define WM_RECEIVE_DATA (WM_USER + 100)
    
    // 在CYourMainDlg类的头文件中,添加消息映射函数声明
    afx_msg LRESULT OnReceiveData(WPARAM wParam, LPARAM lParam);
    
    // 在消息映射中添加自定义消息映射
    BEGIN_MESSAGE_MAP(CYourMainDlg, CDialogEx)
    ON_MESSAGE(WM_RECEIVE_DATA, &CYourMainDlg::OnReceiveData)
    END_MESSAGE_MAP()
    
    
    AI生成项目cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/wsuG3Oi1XcSzZ0vQ4PyqCLbgkrxt.png)
3. 实现主线程的消息处理函数

该消息处理函数主要负责接收并处理来自子线程的消息。以下是对该消息处理函数的具体实现方案:

复制代码
    LRESULT CYourMainDlg::OnReceiveData(WPARAM wParam, LPARAM lParam)
    {
    // 从wParam中获取接收到的数据
    CString* pReceivedData = (CString*)wParam;
    
    // 在UI上显示或处理接收到的数据
    AfxMessageBox(*pReceivedData);
    
    // 清理数据
    delete pReceivedData;
    
    return 0;
    }
    
    
    AI生成项目cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/cHtXIdvC0inF3uWbhDT6ZV8Ykayx.png)
4. 启动异步TCP Client线程

通常是在OnInitDialog或其他按钮响应函数期间进行操作,并且会开始运行客户端进程。

复制代码
    void CYourMainDlg::OnBnClickedStartClient()
    {
    // 启动异步TCP客户端线程
    AfxBeginThread(ClientThread, this);
    }
    
    
    AI生成项目cpp

其中,在AfxBeginThread方法执行过程中(或:当运行AfxBeginThread方法时),会将this指针传送给启动的子线程,并利用其内部的Possemessage功能实现与主线窗口的数据交互

5. 总结与注意事项
  • 利用PostMessage技术可完成线程间的安全通信任务其优势在于操作不阻塞主进程而也不会影响UI进程。
  • 工作进程接收的数据信息可通过CString对象进行内存管理从而避免了局部变量作用域带来的局限性。
  • 消息处理函数必须确保接收数据后及时释放相关资源以防止潜在的内存泄漏问题。

按照前述方法,在异步TCP客户端上实现了与主线程之间的通信功能,并将接收到的数据传递给主线程的UI界面或其他相关的处理模块。

全部评论 (0)

还没有任何评论哟~