|
ATL服务端实现方案,可确保客户端正确接收FD_READ和FD_CLOSE事件
该实现包含完整的消息处理机制,关键点包括:1) 使用WSAAsyncSelect注册网络事件 2) 正确处理FD_ACCEPT/FD_READ/FD_CLOSE事件 3) 错误处理机制。使用时需确保窗口已创建并正确关联消息映射。
ATLSocketServer.h
- #pragma once
- #include <winsock2.h>
- #include <atlbase.h>
- #include <atlwin.h>
- class CATLSocketServer : public CWindowImpl<CATLSocketServer> {
- public:
- DECLARE_WND_CLASS(_T("ATL_SOCKET_SERVER"))
- BEGIN_MSG_MAP(CATLSocketServer)
- MESSAGE_HANDLER(WM_SOCKET_NOTIFY, OnSocketEvent)
- MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
- END_MSG_MAP()
- BOOL Start(int nPort);
- LRESULT OnSocketEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
- LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
- private:
- SOCKET m_listenSocket = INVALID_SOCKET;
- SOCKET m_clientSocket = INVALID_SOCKET;
- };
复制代码 ATLSocketServer.cpp
- "stdafx.h"
- #include "ATLSocketServer.h"
- BOOL CATLSocketServer::Start(int nPort) {
- WSADATA wsa;
- if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
- return FALSE;
- m_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_listenSocket == INVALID_SOCKET)
- return FALSE;
- sockaddr_in serverAddr = {0};
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_port = htons(nPort);
- serverAddr.sin_addr.s_addr = INADDR_ANY;
- if (bind(m_listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
- closesocket(m_listenSocket);
- return FALSE;
- }
- listen(m_listenSocket, SOMAXCONN);
- WSAAsyncSelect(m_listenSocket, m_hWnd, WM_SOCKET_NOTIFY, FD_ACCEPT);
- return TRUE;
- }
- LRESULT CATLSocketServer::OnSocketEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
- SOCKET s = (SOCKET)wParam;
- int event = WSAGETSELECTEVENT(lParam);
- int error = WSAGETSELECTERROR(lParam);
- if (error != 0) {
- closesocket(s);
- return 0;
- }
- switch (event) {
- case FD_ACCEPT: {
- sockaddr_in clientAddr;
- int addrLen = sizeof(clientAddr);
- m_clientSocket = accept(s, (SOCKADDR*)&clientAddr, &addrLen);
- WSAAsyncSelect(m_clientSocket, m_hWnd, WM_SOCKET_NOTIFY, FD_READ | FD_CLOSE);
- break;
- }
- case FD_READ: {
- char buffer[1024];
- int bytesRead = recv(s, buffer, sizeof(buffer), 0);
- if (bytesRead > 0) {
- // 处理接收到的数据
- OutputDebugStringA(buffer);
- }
- break;
- }
- case FD_CLOSE:
- closesocket(s);
- if (s == m_clientSocket) m_clientSocket = INVALID_SOCKET;
- break;
- }
- return 0;
- }
- LRESULT CATLSocketServer::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
- if (m_listenSocket != INVALID_SOCKET) closesocket(m_listenSocket);
- if (m_clientSocket != INVALID_SOCKET) closesocket(m_clientSocket);
- WSACleanup();
- return 0;
- }
复制代码
|
|