/*++
Copyright (c) 2004
模块名:
iomodel.cpp
模块描述:
Winsock 完成端口类实现文件
作者:
PPP elssann@hotmail.com
开发环境:
Visual C++ 6.0, Windows 2000.
修订记录:
创建于: 2004.1.16
最后修改日期:
2004.1.23
--*/
#include <iostream.h>
#include <winsock2.h>
#include <mswsock.h>
#include "iomodel.h"
#define ULONG_PTR DWORD
/*++
函数描述:
构造函数,初始化线程句柄数组,初始化AcceptEx()调用的计数。初始化临界段代码变量。
Arguments:
无。
Return Value:
无。
--*/
CompletionPortModel::CompletionPortModel()
{
for (int i=0; i< MAXTHREAD_COUNT; i++)
{
m_hThreadArray[i] = INVALID_HANDLE_VALUE;
}
m_lAcceptExCounter = 0;
InitializeCriticalSection(&m_ListCriSection);
InitializeCriticalSection(&m_HandleCriSection);
InitializeCriticalSection(&m_IoCriSection);
m_lpHandleLOOKasideLists = NULL;
m_lpIoLookasideLists = NULL;
#ifndef _DEBUG
GetAddressAndPort();
#endif
}//end of CompletionPortModel()
/*++
函数描述:
析构函数,释放链表所有结点。
Arguments:
无。
Return Value:
--*/
CompletionPortModel::~CompletionPortModel()
{
PPER_IO_CONTEXT lpIoNode;
while (m_lpConnectionListHead->pNext)
{
lpIoNode = m_lpConnectionListHead->pNext;
m_lpConnectionListHead->pNext = lpIoNode->pNext;
closesocket(lpIoNode->sClient);
HeapFree(GetProcessHeap(), 0, lpIoNode);
}
while(NULL != m_lpIoLookasideLists)
{
lpIoNode = m_lpIoLookasideLists;
m_lpIoLookasideLists = m_lpIoLookasideLists->pNext;
HeapFree(GetProcessHeap(), 0, lpIoNode);
}
PPER_HANDLE_CONTEXT lpHandleNode;
while(NULL != m_lpHandleLOOKasideLists)
{
lpHandleNode = m_lpHandleLOOKasideLists;
m_lpHandleLOOKasideLists = m_lpHandleLOOKasideLists->pNext;
HeapFree(GetProcessHeap(), 0, lpHandleNode);
}
DeleteCriticalSection(&m_ListCriSection);
DeleteCriticalSection(&m_HandleCriSection);
DeleteCriticalSection(&m_IoCriSection);
}//end of ~CompletionPortModel()
BOOL CompletionPortModel::Init()
/*++
函数描述:
初始化,创建完成端口、创建完成端口线程,并调用类成员函数InitWinsock初始化Winsock、
建立一个监听套接字m_ListenSocket,并将此套接字同完成端口关联起来,获取AcceptEx指针。
Arguments:
无。
Return Value:
函数调用成功返回TRUE,失败返回FALSE。
--*/
{
BOOL bSuccess = InitLinkListHead();
if (FALSE == bSuccess)
{
return FALSE;
}
m_hCOP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
if (NULL == m_hCOP)
{
cout << "CreateIoCompletionPort() failed: " << GetLastError() << endl;
return FALSE;
}
//
//取得系统中CPU的数目,创建和CPU数目相等的线程,如果事先估计到完成端口处理线程会堵塞,
//可以考虑创建 SysInfo.dwNumberOfProcessors*2个线程。一般在单处理器上创建和CPU数目相等
//的线程就可以了
//
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
if (MAXTHREAD_COUNT < SysInfo.dwNumberOfProcessors)
{
SysInfo.dwNumberOfProcessors = MAXTHREAD_COUNT;
}
for (int i=0; i<(int)SysInfo.dwNumberOfProcessors; i++)
{
m_hThreadArray[i] = CreateThread(NULL, 0, CompletionRoutine, (LPVOID)this, 0, NULL);
if (NULL == m_hThreadArray[i])
{
while (i>0)
{
CloseHandle(m_hThreadArray[i-1]);
m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
i--;
}//end of while
cout << "CreateThread() failed: " << GetLastError() << endl;
CloseHandle(m_hCOP);
HeapFree(GetProcessHeap(), 0, m_lpConnectionListHead);
return FALSE;
}
}//end of for
//
//调用InitWinsock函数初始化Winsock、建立一个监听套接字m_ListenSocket,
//并将此套接字同完成端口关联起来,获取AcceptEx指针。
//
bSuccess = InitWinsock();
if (!bSuccess)
{
//
//给完成端口线程发送消息,指示线程退出。
//
PostQueuedCompletionStatus(m_hCOP, 0, NULL, NULL);
CloseThreadHandle();
CloseHandle(m_hCOP);
HeapFree(GetProcessHeap(), 0, m_lpConnectionListHead);
return FALSE;
}
//
//调用BindAndListenSocket()绑定套接字并将套接字置于监听状态
//
bSuccess = BindAndListenSocket();
if (!bSuccess)
{
PostQueuedCompletionStatus(m_hCOP, 0, NULL, NULL);
CloseThreadHandle();
CloseHandle(m_hCOP);
HeapFree(GetProcessHeap(), 0, m_lpConnectionListHead);
return FALSE;
}
return TRUE;
}//end of Init()
/*++
函数描述:
对每一个创建的线程调用CloseHandle()。
Arguments:
无。
Return Value:
无。
--*/
void CompletionPortModel::CloseThreadHandle()
{
for (int i=0; i< MAXTHREAD_COUNT; i++)
{
if (INVALID_HANDLE_VALUE != m_hThreadArray[i])
{
CloseHandle(m_hThreadArray[i]);
m_hThreadArray[i] = INVALID_HANDLE_VALUE;
}
}//end of for
return;
}//end of CloseThreadHandle()
/*++
函数描述:
初始化Winsock,创建一个监听套接字,获取AcceptEx函数指针,为监听套接字分配一个单句柄
数据,并将监听套接字与完成端口hCOP关联。
Arguments:
无。
Return Value:
函数调用成功返回TRUE,失败返回FALSE。
--*/
BOOL CompletionPortModel::InitWinsock()
{
WSADATA wsd;
int nResult = WSAStartup(MAKEWORD(2,2), &wsd);
if (0 != nResult)
{
cout << "WSAStartup() failed" << endl;
return FALSE;
}
m_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP,
NULL, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == m_ListenSocket)
{
cout << "WSASocket() failed: " << WSAGetLastError() << endl;
WSACleanup();
return FALSE;
}
DWORD dwResult;
//
//获取微软SOCKET扩展函数指针
//
nResult = WSAIoctl( m_ListenSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&g_GUIDAcceptEx,
sizeof(g_GUIDAcceptEx),
&lpAcceptEx,
sizeof(lpAcceptEx),
&dwResult,
NULL,
NULL );
if (SOCKET_ERROR == nResult)
{
cout << "Get AcceptEx failed: " << WSAGetLastError() << endl;
closesocket(m_ListenSocket);
WSACleanup();
return FALSE;
}
nResult = WSAIoctl( m_ListenSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&g_GUIDTransmitFile,
sizeof(g_GUIDTransmitFile),
&lpTransmitFile,
sizeof(lpTransmitFile),
&dwResult,
NULL,
NULL);
if (SOCKET_ERROR == nResult)
{
cout << "Get TransmitFile failed: " << WSAGetLastError() << endl;
closesocket(m_ListenSocket);
WSACleanup();
return FALSE;
}
//
//为监听套接字分配一个单句柄数据
//
PPER_HANDLE_CONTEXT lpListenHandleContext = (PPER_HANDLE_CONTEXT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(PER_HANDLE_CONTEXT) );
if (NULL == lpListenHandleContext)
{
closesocket(m_ListenSocket);
WSACleanup();
cout << "HeapAlloc() failed " << endl;
return FALSE;
}
lpListenHandleContext->IoSocket = m_ListenSocket;
lpListenHandleContext->pNext = NULL;
//
//将监听套接字m_ListenSocket和已经建立的完成端口关联起来
//
HANDLE hrc = CreateIoCompletionPort((HANDLE)m_ListenSocket,
m_hCOP,
(ULONG_PTR)lpListenHandleContext,
0 );
if (NULL == hrc)
{
closesocket(m_ListenSocket);
HeapFree(GetProcessHeap(), 0, lpListenHandleContext);
WSACleanup();
cout << "CreateIoCompletionPort failed: " << GetLastError() << endl;
return FALSE;
}
return TRUE;
}//end of InitWinsock()
/*++
函数描述:
private函数,供Init调用。
将监听套接字m_ListenSocket绑定到本地IP地址,并置于监听模式。
Arguments:
无。
Return Value:
函数调用成功返回TRUE,失败返回FALSE。
--*/
BOOL CompletionPortModel::BindAndListenSocket()
{
SOCKADDR_IN InternetAddr;
InternetAddr.sin_family = AF_INET;
#ifdef _DEBUG
InternetAddr.sin_addr.s_addr = inet_addr(LOCALADDRESS);
InternetAddr.sin_port = htons(PORT);
#else
InternetAddr.sin_addr.s_addr = inet_addr(szAddress);
InternetAddr.sin_port = htons(uPort);
#endif
int nResult = bind(m_ListenSoc
评论0