- #include <winsock2.h>
- #include <process.h>
- #pragma comment(lib,"ws2_32.lib")
- #pragma once
- class CAsyncHandler
- {
- public:
- CAsyncHandler()
- {
- }
- virtual ~CAsyncHandler()
- {
- }
- virtual int AcceptNotify( SOCKET hSocket, const char *strClientIP, unsigned short usClientPort )= 0;
- };
- class CAsynch_Event_Handler
- {
- public:
- CAsynch_Event_Handler(void);
- ~CAsynch_Event_Handler(void);
- int Start(CAsyncHandler * phEvent, UINT unPort);
- int Stop(void);
- protected:
- static unsigned int __stdcall AcceptThread(void * lpParam);
- unsigned int AcceptThreadProc();
- private:
- SOCKET m_hListenSocket;
- HANDLE m_hIOThread;
- HANDLE m_hExitThread;
- CAsyncHandler *m_pEventHandler;
- private:
- int OnAccept();
- BOOL InitSocket()
- {
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD( 2, 2 );
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 )
- {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL.
- */
- return FALSE;
- }
- /* Confirm that the WinSock DLL supports 2.2.*/
- /* Note that if the DLL supports versions greater */
- /* than 2.2 in addition to 2.2, it will still return */
- /* 2.2 in wVersion since that is the version we */
- /* requested. */
- if ( LOBYTE( wsaData.wVersion ) != 2 ||
- HIBYTE( wsaData.wVersion ) != 2 )
- {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- WSACleanup( );
- return FALSE;
- }
- return TRUE;
- };
- BOOL ClearSocket()
- {
- WSACleanup( );
- return TRUE;
- };
- };
- ///*************** CPP*****************//
- #include "StdAfx.h"
- #include "Asynch_Event_Handler.h"
- #include <iostream>
- using namespace std;
- CAsynch_Event_Handler::CAsynch_Event_Handler(void)
- {
- m_hListenSocket = INVALID_SOCKET;
- }
- CAsynch_Event_Handler::~CAsynch_Event_Handler(void)
- {
- }
- int CAsynch_Event_Handler::Start(CAsyncHandler * phEvent, UINT unPort)
- {
- if( m_hListenSocket != INVALID_SOCKET )
- {
- return 0;
- }
- InitSocket();
- m_pEventHandler = phEvent;
- struct sockaddr_in serverAddress;
- int err;
- m_hListenSocket = socket(AF_INET, SOCK_STREAM, 0);
- if( INVALID_SOCKET == m_hListenSocket )
- {
- err = WSAGetLastError();
- return err;
- }
- memset(&serverAddress, 0, sizeof(serverAddress));
- serverAddress.sin_family = AF_INET;
- serverAddress.sin_addr.s_addr = 0;
- serverAddress.sin_port = htons( unPort );
- err = bind(m_hListenSocket,
- (struct sockaddr *)&serverAddress,
- sizeof(serverAddress)
- );
- if( err == SOCKET_ERROR )
- {
- err = WSAGetLastError();
- closesocket( m_hListenSocket );
- m_hListenSocket = INVALID_SOCKET;
- return err;
- }
- err = listen( m_hListenSocket, SOMAXCONN );
- if( err == SOCKET_ERROR )
- {
- err = WSAGetLastError();
- closesocket( m_hListenSocket );
- m_hListenSocket = INVALID_SOCKET;
- return err;
- }
- m_hExitThread = CreateEvent( NULL, TRUE, FALSE, NULL );
- m_hIOThread = (HANDLE)
- _beginthreadex(
- NULL,
- 0,
- AcceptThread,
- this,
- 0,
- 0 );
- return 0;
- }
- int CAsynch_Event_Handler::Stop(void)
- {
- if( INVALID_SOCKET == m_hListenSocket )
- {
- return 0;
- }
- closesocket( m_hListenSocket );
- m_hListenSocket = INVALID_SOCKET;
- SetEvent( m_hExitThread );
- if( WAIT_TIMEOUT == WaitForSingleObject( m_hIOThread, 10000 ) )
- {
- TerminateThread( m_hIOThread, 1 );
- }
- CloseHandle( m_hExitThread );
- CloseHandle( m_hIOThread );
- ClearSocket();
- return 0;
- }
- unsigned int CAsynch_Event_Handler::AcceptThreadProc()
- {
- WSANETWORKEVENTS Events;
- WSAEVENT hWaitAll[WSA_MAXIMUM_WAIT_EVENTS] = { INVALID_HANDLE_VALUE };
- hWaitAll[0] = m_hExitThread;
- hWaitAll[1] = WSACreateEvent();
- WSAEventSelect(
- m_hListenSocket,
- hWaitAll[1],
- FD_ACCEPT );
- int nWaitCounts = 2;
- while( TRUE )
- {
- DWORD wt = WSAWaitForMultipleEvents(
- nWaitCounts,
- hWaitAll,
- FALSE,
- INFINITE,
- TRUE );
- if( wt == WAIT_OBJECT_0 )
- {
- //退出线程
- break;
- }
- DWORD index = wt - WSA_WAIT_EVENT_0;
- if( index == 1 )
- {
- int nResult = WSAEnumNetworkEvents(
- m_hListenSocket,
- hWaitAll[1],
- &Events);
- if( 0 == nResult )
- {
- //接受
- if( Events.lNetworkEvents & FD_ACCEPT )
- {
- if( SOCKET_ERROR == Events.iErrorCode[FD_ACCEPT_BIT] )
- {
- continue;
- }
- else
- {
- //接受连接
- OnAccept();
- }
- }
- }
- }
- else if( wt == WAIT_IO_COMPLETION )
- {
- continue;
- }
- else
- {
- break;
- }
- }
- return 0;
- }
- unsigned int __stdcall CAsynch_Event_Handler::AcceptThread(void * lpParam)
- {
- CAsynch_Event_Handler *pAcceptor = (CAsynch_Event_Handler *)lpParam;
- return pAcceptor->AcceptThreadProc();
- }
- int CAsynch_Event_Handler::OnAccept()
- {
- SOCKET AcceptSocket;
- struct sockaddr_in clientAddress;
- int clientAddrLen = sizeof(sockaddr_in);
- AcceptSocket = accept( m_hListenSocket, (sockaddr *)&clientAddress, &clientAddrLen );
- if( INVALID_SOCKET == AcceptSocket )
- {
- return WSAGetLastError();
- }
- else
- {
- DWORD nValue = 1;
- int nLen = sizeof( nValue );
- if( SOCKET_ERROR == setsockopt( AcceptSocket, IPPROTO_TCP ,TCP_NODELAY, (char *)&nValue, nLen ) )
- {
- int err = WSAGetLastError();
- }
- nValue = 16384;
- if( SOCKET_ERROR == setsockopt( AcceptSocket, SOL_SOCKET ,SO_SNDBUF, (char *)&nValue, nLen ) )
- {
- int err = WSAGetLastError();
- }
- if( SOCKET_ERROR == setsockopt( AcceptSocket, SOL_SOCKET ,SO_RCVBUF, (char *)&nValue, nLen ) )
- {
- int err = WSAGetLastError();
- }
- m_pEventHandler->AcceptNotify( AcceptSocket, inet_ntoa( clientAddress.sin_addr ), ntohs( clientAddress.sin_port ) );
- return 0;
- }
- }
本文介绍了一个基于Winsock的异步网络事件处理类的设计与实现。该类通过使用WSAEventSelect进行事件注册,并利用多线程处理客户端连接请求。文章详细展示了如何初始化套接字、设置监听状态、创建事件处理线程以及处理客户端连接。
428

被折叠的 条评论
为什么被折叠?



