|
ATL异步Socket通信实现方案,包含客户端收发功能和对话框数据显示
代码说明:1.使用WSAAsyncSelect实现异步事件通知 2.线程安全的环形缓冲区处理数据接收 3.对话框实时显示收发状态 4.需配套资源文件定义IDD_MAINDLG对话框及控件ID
ATLSocketClient.h
- #pragma once
- #include <atlbase.h>
- #include <atlwin.h>
- #include <winsock2.h>
- #include <vector>
- #include <mutex>
- #define WM_SOCKET_NOTIFY (WM_USER + 200)
- #define RECV_BUFFER_SIZE 8192
- class CATLSocketClient : public CWindowImpl<CATLSocketClient> {
- public:
- DECLARE_WND_CLASS(NULL)
- BEGIN_MSG_MAP(CATLSocketClient)
- MESSAGE_HANDLER(WM_SOCKET_NOTIFY, OnSocketEvent)
- END_MSG_MAP()
- BOOL Connect(LPCTSTR szServer, int nPort);
- BOOL SendData(const CString& strData);
- void SetMessageWindow(HWND hWnd) { m_hMsgWnd = hWnd; }
- private:
- LRESULT OnSocketEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
- void ProcessReceivedData();
-
- SOCKET m_socket = INVALID_SOCKET;
- HWND m_hMsgWnd = NULL;
- std::vector<char> m_recvBuffer;
- std::mutex m_bufferMutex;
- };
复制代码 ATLSocketClient.cpp
- #include "stdafx.h"
- #include "ATLSocketClient.h"
- BOOL CATLSocketClient::Connect(LPCTSTR szServer, int nPort) {
- WSADATA wsa;
- if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
- return FALSE;
- m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_socket == INVALID_SOCKET)
- return FALSE;
- sockaddr_in serverAddr = {0};
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_port = htons(nPort);
- InetPton(AF_INET, szServer, &serverAddr.sin_addr);
- if (connect(m_socket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
- closesocket(m_socket);
- return FALSE;
- }
- WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET_NOTIFY, FD_READ | FD_WRITE | FD_CLOSE);
- return TRUE;
- }
- BOOL CATLSocketClient::SendData(const CString& strData) {
- if (m_socket == INVALID_SOCKET) return FALSE;
-
- int nLen = strData.GetLength();
- int nSent = send(m_socket, CT2A(strData), nLen, 0);
- return nSent == nLen;
- }
- LRESULT CATLSocketClient::OnSocketEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
- if (WSAGETSELECTERROR(lParam)) {
- PostMessage(m_hMsgWnd, WM_SOCKET_NOTIFY, 0, (LPARAM)_T("Socket error"));
- return 0;
- }
- switch(WSAGETSELECTEVENT(lParam)) {
- case FD_READ: {
- char tempBuf[RECV_BUFFER_SIZE];
- int len = recv(m_socket, tempBuf, RECV_BUFFER_SIZE-1, 0);
- if (len > 0) {
- std::lock_guard<std::mutex> lock(m_bufferMutex);
- m_recvBuffer.insert(m_recvBuffer.end(), tempBuf, tempBuf + len);
- PostMessage(m_hMsgWnd, WM_SOCKET_NOTIFY, FD_READ, 0);
- }
- break;
- }
- case FD_CLOSE:
- PostMessage(m_hMsgWnd, WM_SOCKET_NOTIFY, FD_CLOSE, (LPARAM)_T("Connection closed"));
- break;
- }
- return 0;
- }
复制代码 MainDlg.h
- once
- #include "ATLSocketClient.h"
- class CMainDlg : public CDialogImpl<CMainDlg> {
- public:
- enum { IDD = IDD_MAINDLG };
- BEGIN_MSG_MAP(CMainDlg)
- MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
- MESSAGE_HANDLER(WM_SOCKET_NOTIFY, OnSocketNotify)
- COMMAND_ID_HANDLER(IDC_BTN_CONNECT, OnBtnConnect)
- COMMAND_ID_HANDLER(IDC_BTN_SEND, OnBtnSend)
- END_MSG_MAP()
- LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
- LRESULT OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
- LRESULT OnBtnConnect(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
- LRESULT OnBtnSend(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
- private:
- CATLSocketClient m_socketClient;
- };
复制代码 MainDlg.cpp
- "stdafx.h"
- #include "MainDlg.h"
- LRESULT CMainDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
- m_socketClient.Create(m_hWnd);
- m_socketClient.SetMessageWindow(m_hWnd);
- return TRUE;
- }
- LRESULT CMainDlg::OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
- switch(wParam) {
- case FD_READ: {
- CString strRecv;
- {
- std::lock_guard<std::mutex> lock(m_socketClient.m_bufferMutex);
- strRecv = CA2T(m_socketClient.m_recvBuffer.data());
- m_socketClient.m_recvBuffer.clear();
- }
- CString strCurrent;
- GetDlgItemText(IDC_EDIT_RECV, strCurrent);
- SetDlgItemText(IDC_EDIT_RECV, strCurrent + _T("\r\n") + strRecv);
- break;
- }
- case FD_CLOSE:
- SetDlgItemText(IDC_EDIT_STATUS, (LPCTSTR)lParam);
- break;
- default:
- SetDlgItemText(IDC_EDIT_STATUS, _T("Unknown socket event"));
- }
- return 0;
- }
- LRESULT CMainDlg::OnBtnConnect(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
- CString strServer;
- GetDlgItemText(IDC_EDIT_SERVER, strServer);
- int nPort = GetDlgItemInt(IDC_EDIT_PORT);
-
- if (m_socketClient.Connect(strServer, nPort)) {
- SetDlgItemText(IDC_EDIT_STATUS, _T("Connected successfully"));
- } else {
- SetDlgItemText(IDC_EDIT_STATUS, _T("Connection failed"));
- }
- return 0;
- }
- LRESULT CMainDlg::OnBtnSend(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
- CString strSend;
- GetDlgItemText(IDC_EDIT_SEND, strSend);
- if (!strSend.IsEmpty()) {
- if (m_socketClient.SendData(strSend)) {
- SetDlgItemText(IDC_EDIT_STATUS, _T("Data sent successfully"));
- } else {
- SetDlgItemText(IDC_EDIT_STATUS, _T("Send failed"));
- }
- }
- return 0;
- }
复制代码
|
|