SmsCenter/IOCP/IOCP.cpp

1681 lines
38 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "IOCP.h"
#pragma comment(lib, "ws2_32.lib")
#include "..\SmsCenterDlg.h"
/////////////////////////////////////////////////////////////////////////////////////////////
CIOCP::CIOCP()
{
m_pDlg = NULL;
m_listen_socket = INVALID_SOCKET;
m_listen_socket2 = INVALID_SOCKET;
m_bInitSocket = false;
m_bInitSocket2 = false;
m_bInit = false;
m_h_MainLoop = INVALID_HANDLE_VALUE;
m_h_MainLoop2 = INVALID_HANDLE_VALUE;
m_bQuit = false;
}
CIOCP::~CIOCP()
{
Close();
}
/*-------------------------------------------------------------------------------------------
函数功能:关闭并清除资源
函数说明:
函数返回:
-------------------------------------------------------------------------------------------*/
void CIOCP::Close()
{
try
{
int i;
if ( !m_bInit )
return ;
m_bQuit = true;
if (m_h_MainLoop!=INVALID_HANDLE_VALUE )
{
if (WaitForSingleObject(m_h_MainLoop,3000)== WAIT_TIMEOUT )
TerminateThread(m_h_MainLoop,0); //如果退出超时,强制结束线程
CloseHandle(m_h_MainLoop);
m_h_MainLoop = INVALID_HANDLE_VALUE;
}
if (m_h_MainLoop2!=INVALID_HANDLE_VALUE )
{
if ( WaitForSingleObject(m_h_MainLoop2,3000)== WAIT_TIMEOUT )
TerminateThread(m_h_MainLoop2,0); //如果退出超时,强制结束线程
CloseHandle(m_h_MainLoop2);
m_h_MainLoop2 = INVALID_HANDLE_VALUE;
}
PostQueuedCompletionStatus( m_h_iocp, 0, 0, NULL );
CloseHandle( m_h_iocp );
for( i = 0; i < m_n_thread_count; i++ )
{
if (m_h_thread[i]!=INVALID_HANDLE_VALUE )
{
if ( WaitForSingleObject(m_h_thread[i],1000)== WAIT_TIMEOUT )
TerminateThread(m_h_thread[i],0); //如果退出超时,强制结束线程
CloseHandle( m_h_thread[i] );
m_h_thread[i] = INVALID_HANDLE_VALUE;
}
}
Sleep(200); //等待其它的退出
m_KeyList.Close();
CloseMainSocket();
m_bInit = false;
}
catch (...)
{
LOG_APPERROR(_T("T"));
}
}
/*-------------------------------------------------------------------------------------------
函数功能初始化IO结点
函数说明:
函数返回:
-------------------------------------------------------------------------------------------*/
void CIOCP::InitIoContext(IOCP_IO_PTR lp_io)
{
if ( !lp_io )
return ;
try
{
if ( lp_io< &m_KeyList.m_IO[0] || lp_io>&m_KeyList.m_IO[MAX_LOGINUSER] )
return ;
memset( &lp_io->ol, 0, sizeof( WSAOVERLAPPED ) );
//memset( &lp_io->buf, 0, BUFFER_SIZE );
lp_io->wsaBuf.buf = lp_io->buf;
lp_io->wsaBuf.len = BUFFER_SIZE;
lp_io->lRecvLen = 0;
}
catch (...)
{
LOG_APPERROR(_T("T"));
}
}
/*-------------------------------------------------------------------------------------------
函数功能初始化侦听SOCKET端口并和完成端口连接起来。
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::InitSocket()
{
//端口1初始化
m_listen_socket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
if( INVALID_SOCKET == m_listen_socket )
{
return FALSE;
}
//IOCP_KEY_PTR lp_key = m_key_group.GetBlank();
IOCP_KEY_PTR lp_key = m_KeyList.GetBlank_Key();
if ( !lp_key )
return FALSE;
lp_key->socket = m_listen_socket;
HANDLE hRet = CreateIoCompletionPort( (HANDLE)m_listen_socket, m_h_iocp, (ULONG_PTR)lp_key, 0 );
if( hRet == NULL )
{
CloseOneSocket( m_listen_socket );
//m_key_group.RemoveAt( lp_key );
m_KeyList.RemoveAt_Key( lp_key );
return FALSE;
}
//端口2初始化
m_listen_socket2 = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
if( INVALID_SOCKET == m_listen_socket2 )
{
return FALSE;
}
//IOCP_KEY_PTR lp_key2 = m_key_group.GetBlank();
IOCP_KEY_PTR lp_key2 = m_KeyList.GetBlank_Key();
lp_key2->socket = m_listen_socket2;
hRet = CreateIoCompletionPort( (HANDLE)m_listen_socket2, m_h_iocp, (ULONG_PTR)lp_key2, 0 );
if( hRet == NULL )
{
CloseOneSocket( m_listen_socket );
//m_key_group.RemoveAt( lp_key );
m_KeyList.RemoveAt_Key( lp_key );
CloseOneSocket( m_listen_socket2 );
//m_key_group.RemoveAt( lp_key2 );
m_KeyList.RemoveAt_Key( lp_key2 );
return FALSE;
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能:关闭所有线程
函数说明:
函数返回:
-------------------------------------------------------------------------------------------*/
void CIOCP::CloseThreadHandle(int count )
{
if( count <= 0 )
{
return;
}
for( int i= 0; i < count; i++ )
{
if (m_h_thread[i]!=INVALID_HANDLE_VALUE )
{
if ( WaitForSingleObject(m_h_thread[i],1000)== WAIT_TIMEOUT )
TerminateThread(m_h_thread[i],0); //如果退出超时,强制结束线程
CloseHandle( m_h_thread[i] );
m_h_thread[i] = INVALID_HANDLE_VALUE;
}
}
}
/*-------------------------------------------------------------------------------------------
函数功能将侦听端口和自己的IPPORT绑定并开始侦听
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::BindAndListenSocket()
{
SOCKADDR_IN addr;
memset( &addr, 0, sizeof(SOCKADDR_IN) );
addr.sin_family = AF_INET;
//addr.sin_addr.s_addr = inet_addr( ADDR );
//addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_addr.s_addr = m_pDlg->m_Setup.addr;
#ifdef UNICODE
addr.sin_port = htons( DEFAULT_SERVERPORT_UNI );
#else
addr.sin_port = htons( DEFAULT_LISTENPORT );
#endif
int nRet;
nRet = bind( m_listen_socket, (SOCKADDR*)&addr, sizeof( SOCKADDR ) );
if( SOCKET_ERROR == nRet)
{
//cout<<"bind fail!"<<endl;
int er = WSAGetLastError();
return FALSE;
}
nRet = listen( m_listen_socket, 50 );
if( SOCKET_ERROR == nRet )
{
//cout<<"listen fail!"<<endl;
return FALSE;
}
m_bInitSocket = true;
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能根据CPU的数目启动相应数量的数据处理线程
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::StartThread()
{
int i;
SYSTEM_INFO sys_info;
GetSystemInfo( &sys_info );
m_n_thread_count = sys_info.dwNumberOfProcessors*2;
if (m_n_thread_count<2 || m_n_thread_count>MAXTHREAD_COUNT )
m_n_thread_count = MAXTHREAD_COUNT;
//m_n_thread_count = 4;
for( i = 0; i < m_n_thread_count; i++ )
{
m_h_thread[i] = CreateThread( NULL, 0, CompletionRoutine, (LPVOID)this, 0, NULL );
if( INVALID_HANDLE_VALUE == m_h_thread[i] )
{
CloseThreadHandle( i );
CloseHandle( m_h_iocp );
return FALSE;
}
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能:发出一定数量的连接
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::PostAcceptEx()
{
#ifdef _DEBUG
int count = 10;
#else
int count = 30;
#endif
DWORD dwBytes;
BOOL bRet;
for( int i = 0; i < count; i++ )
{
SOCKET socket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
if( INVALID_SOCKET == socket )
{
//cout<<"post accept ex fail!"<<WSAGetLastError()<<endl;
continue;
}
//设置Socket
int ulTemp=1; //将SOCKET设成非阻塞式的SOCKET
//u_long ulTemp=0; //将SOCKET设成阻塞式的SOCKET
//ioctlsocket( socket,FIONBIO,&ulTemp );
ulTemp=128*1024;
setsockopt( socket , SOL_SOCKET, SO_SNDBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
ulTemp=64*1024;
setsockopt( socket , SOL_SOCKET, SO_RCVBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
/*
setsockopt( socket, SOL_SOCKET, SO_DONTLINGER,(const char *)&ulTemp,sizeof(BOOL));
struct linger {
u_short l_onoff;
u_short l_linger;
};
linger m_sLinger;
m_sLinger.l_onoff=0;//(在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
// 如果m_sLinger.l_onoff=0;则功能和2.)作用相同;
m_sLinger.l_linger=0;//(容许逗留的时间为5秒)
int iLen=sizeof(m_sLinger);
int i = setsockopt(socket,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));
*/
// int lLen=sizeof(ulTemp);
// getsockopt( socket , SOL_SOCKET, SO_SNDBUF ,(char *)&ulTemp ,&lLen); //设绶冲
IOCP_IO_PTR lp_io = m_KeyList.GetBlank_IO();
if ( lp_io != NULL )
{
InitIoContext( lp_io );
lp_io->socket = socket;
lp_io->operation = IOCP_ACCEPT;
lp_io->state = SOCKET_STATE_NOT_CONNECT;
/////////////////////////////////////////////////
bRet = lpAcceptEx(
m_listen_socket,
lp_io->socket,
lp_io->buf,
// lp_io->wsaBuf.len - 2 * ( sizeof(SOCKADDR_IN) + 16 ),
0,
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
&dwBytes,&lp_io->ol);
if( ( bRet == FALSE ) && ( WSA_IO_PENDING != WSAGetLastError() ) )
{
closesocket( socket );
//m_io_group.RemoveAt( lp_io );
m_KeyList.RemoveAt_IO( lp_io );
//cout<<"post acceptex fail:"<<WSAGetLastError()<<endl;
continue;
}
}
else
{
int i=10;
}
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能:处理数据函数
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::HandleData(IOCP_IO_PTR lp_io,IOCP_KEY_PTR lp_key, int nFlags)
{
switch( nFlags )
{
case IOCP_COMPLETE_ACCEPT:
{
InitIoContext( lp_io );
lp_io->operation = IOCP_READ;
}
break;
case IOCP_COMPLETE_ACCEPT_READ:
{
/*
lp_io->operation = IOCP_WRITE;
GetAddrAndPort( lp_io->wsaBuf.buf, szAddress, uPort );
//MSG(lp_io->wsaBuf.len);
memset( &lp_io->ol, 0, sizeof(lp_io->ol) );
*/
}
break;
case IOCP_COMPLETE_READ:
{
//cout<<"read a data!*******************************"<<endl;
lp_io->lRecvLen += lp_io->wsaBuf.len;
long lRet=0;
if ( lp_io->m_lLocalPort == DEFAULT_LISTENPORT2 )
lRet = GetFrame_Cmpp(lp_io);
else
lRet = GetFrame(lp_io);
if ( lRet < 0 )
{
//处理帧失败
m_KeyList.RemoveAt_IO( lp_io );
m_KeyList.RemoveAt_Key( lp_key );
closesocket( lp_io->socket );
lp_io->operation = IOCP_END; //关闭后不用处理了
}
else
{
//接收到的数据过大,并且没有合适的包。
if ( lp_io->lRecvLen>=BUFFER_SIZE )
{
m_KeyList.RemoveAt_IO( lp_io );
m_KeyList.RemoveAt_Key( lp_key );
closesocket( lp_io->socket );
lp_io->operation = IOCP_END; //关闭后不用处理了
}
else
{
//重新开始投射io
lp_io->operation = IOCP_READ;
memset( &lp_io->ol, 0, sizeof(lp_io->ol) );
lp_io->wsaBuf.buf = lp_io->buf + lp_io->lRecvLen;
lp_io->wsaBuf.len = BUFFER_SIZE-lp_io->lRecvLen;
}
}
}
break;
case IOCP_COMPLETE_WRITE:
{
try
{
IOCP_IO_SEND_PTR ioS = (IOCP_IO_SEND_PTR)lp_io;
if ( ioS->wsaBuf.len >0 )
{
if ( ioS->wsaBuf.buf )
delete ioS->wsaBuf.buf;
ioS->wsaBuf.buf = NULL;
}
delete ioS;
}
catch (...)
{
LOG_APPERROR(_T("T"));
break;
}
}
break;
default:
{
//cout<<"handleData do nothing!*********************"<<endl;
return FALSE;
}
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能:发出一些重叠动作
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::DataAction(IOCP_IO_PTR lp_io, IOCP_KEY_PTR lp_key )
{
DWORD dwBytes;
int nRet;
DWORD dwFlags;
switch( lp_io->operation )
{
case IOCP_WRITE:
{
nRet = WSASend(
lp_io->socket,
&lp_io->wsaBuf,
1,
&dwBytes,
0,
&lp_io->ol,NULL);
if( ( nRet == SOCKET_ERROR ) && ( WSAGetLastError() != WSA_IO_PENDING ) )
{
m_KeyList.RemoveAt_IO( lp_io );
m_KeyList.RemoveAt_Key( lp_key );
closesocket( lp_io->socket );
return FALSE;
}
}
break;
case IOCP_WRITE2:
{
/*
IOCP_IO_SEND_PTR ioS = (IOCP_IO_SEND_PTR)lp_io;
ioS->operation = IOCP_WRITE;
nRet = WSASend(
lp_key->socket,
&ioS->wsaBuf[ioS->lSendNowIndex-1],
1,
&dwBytes,
0,
&ioS->ol,NULL);
/*
if( ( nRet == SOCKET_ERROR ) && ( WSAGetLastError() != WSA_IO_PENDING ) )
{
//cout<<"WSASend fail!----------------------------------------"<<WSAGetLastError()<<endl;
closesocket( lp_io->socket );
//m_io_group.RemoveAt( lp_io );
m_KeyList.RemoveAt_IO( lp_io );
//m_key_group.RemoveAt( lp_key );
m_KeyList.RemoveAt_Key( lp_key );
return FALSE;
}
*/
}
break;
case IOCP_READ:
{
//cout<<"post a read data!-----------------------------------------"<<endl;
dwFlags = 0;
nRet = WSARecv(
lp_io->socket,
&lp_io->wsaBuf,
1,
&dwBytes,
&dwFlags,
&lp_io->ol,NULL);
if( ( nRet == SOCKET_ERROR ) && ( WSAGetLastError() != WSA_IO_PENDING ) )
{
m_KeyList.RemoveAt_IO( lp_io );
m_KeyList.RemoveAt_Key( lp_key );
closesocket( lp_io->socket );
return FALSE;
}
}
break;
case IOCP_END:
break;
default:
{
//cout<<"DataAction do nothing!------------------------------------------"<<endl;
return FALSE;
}
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能得到MS封装的SOCKET函数指针这样可以提高速度
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::GetFunPointer()
{
DWORD dwRet,nRet;
nRet = WSAIoctl(
m_listen_socket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&g_GUIDAcceptEx,
sizeof(g_GUIDAcceptEx),
&lpAcceptEx,
sizeof(lpAcceptEx),
&dwRet,NULL,NULL);
if( SOCKET_ERROR == nRet )
{
CloseOneSocket(m_listen_socket);
//cout<<"get acceptex fail!"<<WSAGetLastError()<<endl;
return FALSE;
}
nRet = WSAIoctl(
m_listen_socket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&g_GUIDTransmitFile,
sizeof(g_GUIDTransmitFile),
&lpTransmitFile,
sizeof(lpTransmitFile),
&dwRet,NULL,NULL);
if(nRet == SOCKET_ERROR )
{
CloseOneSocket(m_listen_socket);
//cout<<"get transmitfile fail!"<<WSAGetLastError()<<endl;
return FALSE;
}
nRet = WSAIoctl(
m_listen_socket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&g_GUIDAcceptExaddrs,
sizeof(g_GUIDAcceptExaddrs),
&lpGetAcceptExSockAddrs,
sizeof(lpGetAcceptExSockAddrs),
&dwRet,NULL,NULL);
if(nRet == SOCKET_ERROR )
{
CloseOneSocket(m_listen_socket);
//cout<<"get transmitfile fail!"<<WSAGetLastError()<<endl;
return FALSE;
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能:看看是否有连接了,但很长时间没有数据的“无效连接”,有的话,就踢掉
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
void CIOCP::CheckForInvalidConnection()
{
try
{
TCHAR szMsg[256]={0};
DWORD dwNow = ::GetTickCount();
IOCP_IO_PTR lp_io = m_KeyList.m_IO;
if ( !lp_io )
return ;
for ( int i=0 ; i< MAX_LOGINUSER ; i++ )
{
if ( lp_io[i].socket != NULL && lp_io[i].socket!=INVALID_SOCKET && lp_io[i].lRandID>0 )
{
if (lp_io[i].dwAcceptTime>0 && lp_io[i].state != SOCKET_STATE_CONNECT_AND_READ )
{
/*
op_len = sizeof(op);
nRet = getsockopt( lp_io[i].socket, SOL_SOCKET, SO_CONNECT_TIME, (char*)&op, &op_len );
if( SOCKET_ERROR == nRet )
{
continue;
}
if( op != 0xffffffff && op > 3 ) //3秒连接超时
{
sprintf(szMsg , "[%d]%s:%d 连接超时!" , lp_io[i].m_lLocalPort,lp_io[i].m_szIP,lp_io[i].m_lPort);
m_pDlg->AddLog(szMsg);
closesocket( lp_io[i].socket );
}
*/
if ( dwNow - lp_io[i].dwAcceptTime >5000 ) //10秒连接超时
{
_stprintf(szMsg , _T("[%d]%s:%d 连接超时!") , lp_io[i].m_lLocalPort,lp_io[i].m_szIP,lp_io[i].m_lPort);
m_pDlg->AddLog(szMsg);
closesocket( lp_io[i].socket );
}
}
if ( lp_io[i].state == SOCKET_STATE_CONNECT_AND_READ )
{
if ( lp_io[i].dwEndRecvFrame>0 )
{
if ( dwNow - lp_io[i].dwEndRecvFrame > RECVREFRESH_TIMEOUT )
{
lp_io[i].m_lID = 199992; //断线退出的标志
closesocket( lp_io[i].socket );
}
}
else
{
if ( dwNow - lp_io[i].dwAcceptTime > 40000 ) //30秒没收到正确的包就超时
{
_stprintf(szMsg , _T("[%d]%s:%d 接收数据超时!") , lp_io[i].m_lLocalPort,lp_io[i].m_szIP,lp_io[i].m_lPort);
m_pDlg->AddLog(szMsg);
closesocket( lp_io[i].socket );
}
}
}
}
}
}
catch (...)
{
LOG_APPERROR(_T("T"));
}
}
/*-------------------------------------------------------------------------------------------
函数功能注册FD_ACCEPTG事件到m_h_accept_event事件以便所有发出去的连接耗耗尽时得到通知。
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::RegAcceptEvent()
{
int nRet;
m_h_accept_event = CreateEvent( NULL, FALSE, FALSE, NULL );
if( NULL == m_h_accept_event )
{
return FALSE;
}
nRet = WSAEventSelect( m_listen_socket, m_h_accept_event, FD_ACCEPT );
if( nRet != 0 )
{
CloseHandle( m_h_accept_event );
return FALSE;
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能得到连接上来的客户端IP和PORT
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::GetAddrAndPort(char*buf,char ip[],UINT &port)
{
int len = BUFFER_SIZE - sizeof( SOCKADDR_IN ) - 16;
char *lp_buf = buf + len; //直接读取远端地址
SOCKADDR_IN addr;
memcpy( &addr, lp_buf, sizeof( SOCKADDR_IN ) );
port = ntohl( addr.sin_port );
strcpy( ip, inet_ntoa( addr.sin_addr ) );
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/*-------------------------------------------------------------------------------------------
函数功能初始化完成端口及相关的所有东西并发出每一个10个连接.
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
BOOL CIOCP::Init()
{
BOOL b1;
BOOL b2;
WSAData data;
if( WSAStartup( MAKEWORD(2,2),&data) != 0 )
{
//cout<<"WSAStartup fail!"<<WSAGetLastError() << endl;
return FALSE;
}
m_KeyList.Init(m_pDlg);
m_h_iocp = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, NULL, 0 );
if( NULL == m_h_iocp )
{
//cout << "CreateIoCompletionPort() failed: " << GetLastError() << endl;
return FALSE;
}
if( !StartThread() )
{
//cout<<"start thread fail!"<<endl;
Close();
//PostQueuedCompletionStatus( m_h_iocp, 0, NULL, NULL );
//CloseHandle( m_h_iocp );
return FALSE;
}
if( !InitSocket() )
{
Close();
//PostQueuedCompletionStatus( m_h_iocp, 0, NULL, NULL );
//CloseHandle( m_h_iocp );
return FALSE;
}
if ( !BindAndListenSocket() ) //绑定端口1
{
Close();
return FALSE;
}
m_bInitSocket2=false; //不启用7890端口
/*
#ifndef UNICODE
if ( !BindAndListenSocket2()) //绑定端口2
{
Close();
return FALSE;
}
#endif
*/
if( !m_bInitSocket && !m_bInitSocket2 ) //两个端口初始化都不成功
{
Close();
//PostQueuedCompletionStatus( m_h_iocp, 0, NULL, NULL );
//CloseHandle( m_h_iocp );
//CloseMainSocket();
return FALSE;
}
if ( !GetFunPointer() )
{
Close();
//PostQueuedCompletionStatus( m_h_iocp, 0, NULL, NULL );
//CloseHandle( m_h_iocp );
//CloseMainSocket();
return FALSE;
}
b1 = true;
if (m_bInitSocket)
b1=PostAcceptEx();
b2 = true;
if (m_bInitSocket2)
b2=PostAcceptEx2();
if ( !b1 && !b2 )
{
Close();
//PostQueuedCompletionStatus( m_h_iocp, 0, NULL, NULL );
//CloseHandle( m_h_iocp );
//CloseMainSocket();
return FALSE;
}
b1 = true;
if (m_bInitSocket)
b1=RegAcceptEvent();
b2 = true;
if (m_bInitSocket2)
b1=RegAcceptEvent2();
if ( !b1 && !b2 )
{
Close();
//PostQueuedCompletionStatus( m_h_iocp, 0, NULL, NULL );
//CloseHandle( m_h_iocp );
//CloseMainSocket();
return FALSE;
}
m_bInit = true;
m_bQuit = false; //主线程不允许退出
m_h_MainLoop = CreateThread( NULL, 0, MainLoop, (LPVOID)this, 0, NULL );
if ( m_h_MainLoop == INVALID_HANDLE_VALUE ) //主线程创建不成功
{
this->Close();
return false;
}
//if( m_bInitSocket2 )
//{
m_h_MainLoop2 = CreateThread( NULL, 0, MainLoop2, (LPVOID)this, 0, NULL );
if ( m_h_MainLoop2 == INVALID_HANDLE_VALUE ) //主线程创建不成功
{
this->Close();
return false;
}
//}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
函数功能:主循环
函数说明:
函数返回成功TRUE失败FALSE
-------------------------------------------------------------------------------------------*/
DWORD CIOCP::MainLoop(LPVOID lp_param)
{
try
{
AutoCoInitializeEx AutoCoInit; //自动初始化与结束Com环境
CIOCP * piocp = (CIOCP *)lp_param;
DWORD dwRet;
while( !piocp->m_bQuit )
{
dwRet = WaitForSingleObject( piocp->m_h_accept_event, 300 );
switch( dwRet )
{
case WAIT_FAILED:
{
CString str;
str.Format( _T("Accept_Event Error:%d") , GetLastError());
piocp->m_pDlg->AddLog(str);
piocp->m_pDlg->ON_TD_StopAll2(); //可能是资源不够造成失败,停止所有通道
piocp->PostAcceptEx();
//AfxMessageBox( _T("accept_event Error!") );
//PostQueuedCompletionStatus( m_h_iocp, 0, 0, NULL );
//return FALSE;
}
break;
case WAIT_TIMEOUT:
{
//CheckForInvalidConnection();
}
break;
case WAIT_OBJECT_0: //接收到了所有发出的连接都用光了的消息,再次发出连接
{
piocp->PostAcceptEx();
}
break;
}
/*
#ifndef UNICODE
dwRet = WaitForSingleObject( piocp->m_h_accept_event2, 300 );
switch( dwRet )
{
case WAIT_FAILED:
{
AfxMessageBox( _T("accept_event2 Error!") );
//PostQueuedCompletionStatus( m_h_iocp, 0, 0, NULL );
//return FALSE;
}
break;
case WAIT_TIMEOUT:
{
//CheckForInvalidConnection();
}
break;
case WAIT_OBJECT_0: //接收到了所有发出的连接都用光了的消息,再次发出连接
{
piocp->PostAcceptEx2();
}
break;
}
#endif
*/
/*
nCount ++;
if ( nCount>5 ) //每5秒检测一次超时
{
nCount=0;
//每个event等待1秒加起来就是2秒可以检测连接没有数据的socket
piocp->CheckForInvalidConnection();
}
*/
}
return TRUE;
}
catch(...)
{
LOG_APPERROR(_T("T"));
return false;
}
}
/*-------------------------------------------------------------------------------------------
函数功能:数据处理线程函数
函数说明:
函数返回:
-------------------------------------------------------------------------------------------*/
DWORD CIOCP::CompletionRoutine(LPVOID lp_param)
{
USES_CONVERSION;
try
{
AutoCoInitializeEx AutoCoInit; //自动初始化与结束Com环境
CIOCP* lp_this = (CIOCP*)lp_param;
int nRet;
BOOL bRet;
DWORD dwBytes = 0;
HANDLE hRet;
IOCP_KEY_PTR lp_key = NULL;
IOCP_IO_PTR lp_io = NULL;
LPWSAOVERLAPPED lp_ov = NULL;
IOCP_KEY_PTR lp_new_key = NULL;
while( TRUE )
{
bRet = GetQueuedCompletionStatus( lp_this->m_h_iocp, &dwBytes, (PULONG_PTR)&lp_key, &lp_ov, INFINITE );
if ( lp_this->m_bQuit ) //收到退出信号
return 0;
lp_io = (IOCP_IO_PTR)lp_ov;
if ( lp_io && !AfxIsValidAddress(&lp_io->operation,4,true) ) //收到的lp_io有问题
continue;
if ( (bRet==0 || dwBytes ==0 ) && lp_io && lp_io->operation== IOCP_WRITE ) //删除不成功的Write
{
lp_this->HandleData( lp_io, lp_key, IOCP_COMPLETE_WRITE );
continue;
}
if( bRet == 0 )
{
if ( lp_key && lp_io && lp_io->lRandID>0 )
{
lp_this->m_KeyList.RemoveAt_IO( lp_io );
lp_this->m_KeyList.RemoveAt_Key( lp_key );
continue;
}
if ( (!lp_key && !lp_io) )
{
continue;
//return 0; //已退出
}
//cout << "GetQueuedCompletionStatus() failed: " << GetLastError() << endl;
//continue;
}
if( NULL == lp_key )
{
continue;
//return 0;
}
if( lp_io == NULL )
{
//cout<<"recv a null CIoContext!"<<endl;
continue;
}
if ( lp_io&& lp_io->operation!=IOCP_WRITE && (lp_io< &lp_this->m_KeyList.m_IO[0] || lp_io>&lp_this->m_KeyList.m_IO[MAX_LOGINUSER]) )
continue;
if ( lp_key && (lp_key< &lp_this->m_KeyList.m_Key[0] || lp_key>&lp_this->m_KeyList.m_Key[MAX_LOGINUSER]) )
continue;
if( ( IOCP_ACCEPT != lp_io->operation ) && ( 0 == dwBytes ) )
{
closesocket( lp_io->socket );
//lp_this->m_io_group.RemoveAt( lp_io );
//lp_this->m_key_group.RemoveAt( lp_key );
lp_this->m_KeyList.RemoveAt_IO( lp_io );
lp_this->m_KeyList.RemoveAt_Key( lp_key );
//MSG("一个用户退出了");
continue;
}
switch( lp_io->operation )
{
case IOCP_ACCEPT:
{
//cout<<"接收到一个连接"<<endl;
lp_io->state = SOCKET_STATE_CONNECT;
if( dwBytes > 0 )
{
lp_io->state = SOCKET_STATE_CONNECT_AND_READ;
//cout<<"读取到一条数据"<<endl;
}
//取IP地址与端口信息
SOCKADDR *local=NULL;
SOCKADDR *remote=NULL;
int local_len;
int remote_len;
lp_this->lpGetAcceptExSockAddrs(lp_io->buf,0,sizeof(SOCKADDR_IN) + 16,sizeof(SOCKADDR_IN) + 16,&local,&local_len,&remote,&remote_len);
SOCKADDR_IN * pAA = ((SOCKADDR_IN *)local);
SOCKADDR_IN * pBB = ((SOCKADDR_IN *)remote);
#ifdef UNICODE
_tcscpy(lp_io->m_szIP,A2W(inet_ntoa(pBB->sin_addr)));
#else
strcpy(lp_io->m_szIP,inet_ntoa(pBB->sin_addr));
#endif
lp_io->m_lPort = ntohs(pBB->sin_port);
lp_io->m_lLocalPort = ntohs(pAA->sin_port);
#ifdef UNICODE
if (lp_io->m_lLocalPort == DEFAULT_SERVERPORT_UNI )
#else
if (lp_io->m_lLocalPort == DEFAULT_LISTENPORT )
#endif
{
nRet = setsockopt(
lp_io->socket,
SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT,
( char* )&lp_this->m_listen_socket,
sizeof( lp_this->m_listen_socket ) );
}
else
{
nRet = setsockopt(
lp_io->socket,
SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT,
( char* )&lp_this->m_listen_socket2,
sizeof( lp_this->m_listen_socket2 ) );
}
if( SOCKET_ERROR == nRet )
{
closesocket( lp_io->socket );
//lp_this->m_io_group.RemoveAt( lp_io );
lp_this->m_KeyList.RemoveAt_IO( lp_io );
//cout<<"update socket fail!"<<WSAGetLastError()<<endl;
continue;
}
//lp_new_key = lp_this->m_key_group.GetBlank();
lp_new_key = lp_this->m_KeyList.GetBlank_Key();
if( lp_new_key == NULL )
{
closesocket( lp_io->socket );
continue;
}
lp_new_key->socket = lp_io->socket;
lp_io->pKey = lp_new_key; //记录对应的key参数
lp_io->dwAcceptTime = ::GetTickCount(); //Accept的时间
//将新建立的SOCKET同完成端口关联起来。
hRet = CreateIoCompletionPort(
( HANDLE )lp_io->socket,
lp_this->m_h_iocp,
(ULONG_PTR)lp_new_key,0 );
if( NULL == hRet )
{
lp_this->m_KeyList.RemoveAt_Key( lp_new_key );
lp_this->m_KeyList.RemoveAt_IO( lp_io );
closesocket( lp_io->socket );
continue;
}
//处理数据
lp_this->HandleData( lp_io, lp_new_key,IOCP_COMPLETE_ACCEPT );
bRet = lp_this->DataAction( lp_io, lp_new_key );
if( FALSE == bRet )
{
continue;
}
}
break;
case IOCP_READ:
{
if( SOCKET_STATE_CONNECT_AND_READ != lp_io->state )
{
lp_io->state = SOCKET_STATE_CONNECT_AND_READ;
}
lp_io->wsaBuf.len = dwBytes;
lp_this->HandleData( lp_io, lp_key, IOCP_COMPLETE_READ );
bRet = lp_this->DataAction( lp_io, lp_key );
if( FALSE == bRet )
{
continue;
}
}
break;
case IOCP_WRITE:
{
lp_this->HandleData( lp_io, lp_key, IOCP_COMPLETE_WRITE );
if( FALSE == bRet )
{
continue;
}
}
break;
default:
{
continue;
}
break;
}
}
return 0;
}
catch (... )
{
LOG_APPERROR(_T("T"));
return 1;
}
}
void CIOCP::CloseMainSocket()
{
CloseOneSocket(m_listen_socket);
CloseOneSocket(m_listen_socket2);
}
BOOL CIOCP::BindAndListenSocket2()
{
SOCKADDR_IN addr;
memset( &addr, 0, sizeof(SOCKADDR_IN) );
addr.sin_family = AF_INET;
//addr.sin_addr.s_addr = inet_addr( ADDR );
//addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_addr.s_addr = m_pDlg->m_Setup.addr;
addr.sin_port = htons( DEFAULT_LISTENPORT2 );
int nRet;
nRet = bind( m_listen_socket2, (SOCKADDR*)&addr, sizeof( SOCKADDR ) );
if( SOCKET_ERROR == nRet )
{
//cout<<"bind fail!"<<endl;
return FALSE;
}
nRet = listen( m_listen_socket2, 20 );
if( SOCKET_ERROR == nRet )
{
//cout<<"listen fail!"<<endl;
return FALSE;
}
m_bInitSocket2 = true;
return TRUE;
}
void CIOCP::CloseOneSocket(SOCKET &socket)
{
if ( socket != INVALID_SOCKET )
{
closesocket(socket);
socket = INVALID_SOCKET;
}
}
BOOL CIOCP::PostAcceptEx2()
{
#ifdef _DEBUG
int count = 10;
#else
int count = 30;
#endif
DWORD dwBytes;
BOOL bRet;
for( int i = 0; i < count; i++ )
{
SOCKET socket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
if( INVALID_SOCKET == socket )
{
//cout<<"post accept ex fail!"<<WSAGetLastError()<<endl;
continue;
}
/*
//设置Socket
u_long ulTemp=1; //将SOCKET设成非阻塞式的SOCKET
//u_long ulTemp=0; //将SOCKET设成阻塞式的SOCKET
ioctlsocket( socket,FIONBIO,&ulTemp );
ulTemp=64000;
setsockopt( socket , SOL_SOCKET, SO_SNDBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
ulTemp=64000;
setsockopt( socket , SOL_SOCKET, SO_RCVBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
setsockopt( socket, SOL_SOCKET, SO_DONTLINGER,(const char *)&ulTemp,sizeof(BOOL));
struct linger {
u_short l_onoff;
u_short l_linger;
};
linger m_sLinger;
m_sLinger.l_onoff=0;//(在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
// 如果m_sLinger.l_onoff=0;则功能和2.)作用相同;
m_sLinger.l_linger=0;//(容许逗留的时间为5秒)
int iLen=sizeof(m_sLinger);
int i = setsockopt(socket,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));
*/
//IOCP_IO_PTR lp_io = m_io_group.GetBlank();
IOCP_IO_PTR lp_io = m_KeyList.GetBlank_IO();
if ( lp_io != NULL )
{
InitIoContext( lp_io );
lp_io->socket = socket;
lp_io->operation = IOCP_ACCEPT;
lp_io->state = SOCKET_STATE_NOT_CONNECT;
/////////////////////////////////////////////////
bRet = lpAcceptEx(
m_listen_socket2,
lp_io->socket,
lp_io->buf,
// lp_io->wsaBuf.len - 2 * ( sizeof(SOCKADDR_IN) + 16 ),
0,
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
&dwBytes,&lp_io->ol);
if( ( bRet == FALSE ) && ( WSA_IO_PENDING != WSAGetLastError() ) )
{
closesocket( socket );
//m_io_group.RemoveAt( lp_io );
m_KeyList.RemoveAt_IO( lp_io );
//cout<<"post acceptex fail:"<<WSAGetLastError()<<endl;
continue;
}
}
else
{
int i=10;
}
}
return TRUE;
}
BOOL CIOCP::RegAcceptEvent2()
{
int nRet;
m_h_accept_event2 = CreateEvent( NULL, FALSE, FALSE, NULL );
if( NULL == m_h_accept_event2 )
{
return FALSE;
}
nRet = WSAEventSelect( m_listen_socket2, m_h_accept_event2, FD_ACCEPT );
if( nRet != 0 )
{
CloseHandle( m_h_accept_event2 );
return FALSE;
}
return TRUE;
}
long CIOCP::GetFrame(IOCP_IO_PTR lp_io)
{
try
{
int iGetFrame=0;
for ( int i=0 ; i<lp_io->lRecvLen ; i++ )
{
if ( i+sizeof(Socket_Head) > (DWORD)lp_io->lRecvLen )
{
//i--;
break;
}
Socket_Head SHead={0};
memcpy(&SHead,lp_io->buf+i,sizeof(Socket_Head)); i=i+sizeof(Socket_Head);
long lGetLen=SHead.lFrameLen;
if ( SHead.bCompress )
lGetLen = SHead.lCompressLen;
if ( SHead.lFuncType <=0 || SHead.lFuncType > 100000 ||
SHead.lCompressLen<0 || SHead.lCompressLen>BUFFER_SIZE ||
SHead.lFrameLen<0 || SHead.lFrameLen>BUFFER_SIZE ) //简单判断收到的帧是否有问题
{
return -1; //数据不对,关闭连接
}
if ( i+lGetLen>lp_io->lRecvLen) //数据不够
{
i=i-sizeof(Socket_Head);
//i--;
break;
}
lp_io->dwEndRecvFrame = ::GetTickCount();
if ( SHead.lFuncType == SMSFUNC_TEST && lp_io->m_lUserID>0 ) //直接回复SMSFunc_Test
{
ANS_Test * pTestRet = new ANS_Test;
pTestRet->lTemp = ::GetTickCount();
CSmsCenterDlg::SendFrame(lp_io, SMSFUNC_TEST , (BYTE*)pTestRet , sizeof(ANS_Test) ); //发送返回
}
else
{
IOCP_SQL_PTR pSql = m_KeyList.GetBlank_SQL();
if ( pSql )
{
try
{
//CProcessSocket * pProcess = m_KeyList.GetBlank_Process();
CProcessSocket * pProcess = new CProcessSocket;
if ( pProcess )
{
BOOL bOK = true;
pProcess->SetDlg(m_pDlg);
pProcess->IOCP_setSQL(pSql);
Cmpp_Head head={0};
bOK = pProcess->IOCP_GetFrameData(lp_io , SHead , head,(BYTE*)(lp_io->buf+i) , lGetLen);
if ( bOK ) //启动线程处理
{
iGetFrame ++;
QueueUserWorkItem(CProcessSocket::IOCP_Process, (PVOID)pProcess, WT_EXECUTELONGFUNCTION);
}
else
{
//释放资源
pProcess->m_bUse = false;
pProcess->m_lRandID=0;
pSql->bUse = false;
pSql->lRandID = 0;
//暂时不删除此对像,防止出错
delete pProcess; //删除new的对像
}
}
else
{
AfxMessageBox(_T("new Process error"));
}
}
catch(...)
{
LOG_APPERROR(_T("T"));
pSql->bUse = false; //有异常,恢复正常模式
pSql->lRandID = 0;
}
}
}
i=i+lGetLen;
i=i-1;
}
if ( i >= lp_io->lRecvLen ) //数据刚刚好
{
lp_io->lRecvLen = 0;
}
else
{
if ( i> 0 )
{
//转移数据
lp_io->lRecvLen = lp_io->lRecvLen-i;
memcpy(lp_io->buf , lp_io->buf+i , lp_io->lRecvLen );
}
}
return iGetFrame;
}
catch (...)
{
LOG_APPERROR(_T("T"));
}
return -1;
}
long CIOCP::GetFrame_Cmpp(IOCP_IO_PTR lp_io)
{
try
{
int iGetFrame=0;
for ( int i=0 ; i<lp_io->lRecvLen ; i++ )
{
if ( i+sizeof(Cmpp_Head) > (DWORD)lp_io->lRecvLen )
{
//i--;
break;
}
Cmpp_Head SHead={0};
memcpy(&SHead,lp_io->buf+i,sizeof(Cmpp_Head)); i=i+sizeof(Cmpp_Head);
SHead.Command_Id = ntohl(SHead.Command_Id);
SHead.Sequence_Id= ntohl(SHead.Sequence_Id);
SHead.Total_Length = ntohl(SHead.Total_Length);
long lGetLen=SHead.Total_Length-sizeof(Cmpp_Head);
if ( SHead.Total_Length <=0 || SHead.Total_Length>BUFFER_SIZE ) //简单判断收到的帧是否有问题
{
return -1; //数据不对,关闭连接
}
if ( i+lGetLen>lp_io->lRecvLen) //数据不够
{
i=i-sizeof(Cmpp_Head);
//i--;
break;
}
lp_io->dwEndRecvFrame = ::GetTickCount();
/*
if ( SHead.Command_Id == CMPP_ACTIVE_TEST && lp_io->m_lUserID>0 ) //直接回复SMSFunc_Test
{
Cmpp_Active_Test_Resp * pActive = new Cmpp_Active_Test_Resp;
memset(pActive , 0 , sizeof(Cmpp_Active_Test_Resp));
CSmsCenterDlg::SendFrame_Cmpp(lp_io, CMPP_ACTIVE_TEST_RESP ,SHead.Sequence_Id, (BYTE*)pActive , sizeof(Cmpp_Active_Test_Resp) ); //发送返回
}
else
{
IOCP_SQL_PTR pSql = m_KeyList.GetBlank_SQL();
if ( pSql )
{
//CProcessSocket * pProcess = m_KeyList.GetBlank_Process();
CProcessSocket * pProcess = new CProcessSocket;
if ( pProcess )
{
BOOL bOK = true;
pProcess->SetDlg(m_pDlg);
pProcess->IOCP_setSQL(pSql);
Socket_Head head={0};
bOK = pProcess->IOCP_GetFrameData(lp_io , head,SHead , (BYTE*)(lp_io->buf+i) , lGetLen);
if ( bOK ) //启动线程处理
{
iGetFrame ++;
QueueUserWorkItem(CProcessSocket::IOCP_Process, (PVOID)pProcess, WT_EXECUTELONGFUNCTION);
}
else
{
//释放资源
pProcess->m_bUse = false;
pProcess->m_lRandID=0;
pSql->bUse = false;
pSql->lRandID = 0;
//暂时不删除此对像,防止出错
delete pProcess; //删除new的对像
}
}
}
}
*/
i=i+lGetLen;
i=i-1;
}
if ( i >= lp_io->lRecvLen ) //数据刚刚好
{
lp_io->lRecvLen = 0;
}
else
{
if ( i> 0 )
{
//转移数据
lp_io->lRecvLen = lp_io->lRecvLen-i;
memcpy(lp_io->buf , lp_io->buf+i , lp_io->lRecvLen );
}
}
return iGetFrame;
}
catch (...)
{
LOG_APPERROR(_T("T"));
}
return -1;
}
void CIOCP::SetDlg(CSmsCenterDlg *pDlg)
{
m_pDlg = pDlg;
}
void CIOCP::InitIoContext_Send(IOCP_IO_SEND_PTR lp_io)
{
memset( &lp_io->ol, 0, sizeof( WSAOVERLAPPED ) );
}
void CIOCP::CheckForInvalidSQLConnection()
{
try
{
TCHAR szMsg[256]={0};
DWORD dwNow = ::GetTickCount();
/*
LPVOID * lpProcess = m_KeyList.m_Process;
if ( lpProcess )
{
for ( int i=0 ; i<MAX_SQLCONNECT; i++ )
{
CProcessSocket * pSocket = (CProcessSocket *)lpProcess[i];
if ( pSocket && pSocket->m_adoConnection.IsOpen() )
{
if ( pSocket->m_bUse && pSocket->m_lRandID>0 ) //在使用中的SQL,40分钟超时
{
if ( dwNow - pSocket->m_dwEndUse > SQL_TIMEOUT_USE )
{
pSocket->m_AdoRS.Close();
pSocket->m_AdoRS2.Close();
pSocket->m_adoConnection.Close();
pSocket->m_bUse = false;
pSocket->m_lRandID = 0;
sprintf(szMsg, "SQL:%d 操作超时,自动断连!" , i );
m_pDlg->AddLog(szMsg);
}
}
else
{
//不在使用中的SQL,20分钟超时
if ( dwNow - pSocket->m_dwEndUse > SQL_TIMEOUT_DISUSE )
{
pSocket->m_AdoRS.Close();
pSocket->m_AdoRS2.Close();
pSocket->m_adoConnection.Close();
pSocket->m_bUse = false;
pSocket->m_lRandID = 0;
sprintf(szMsg, "SQL:%d 超时未使用,自动断连!" , i );
m_pDlg->AddLog(szMsg);
}
}
}
}
}
*/
IOCP_SQL_PTR pSql = m_KeyList.m_SQL;
if ( pSql )
{
for ( int i=0 ; i<MAX_SQLCONNECT; i++ )
{
if ( pSql[i].adoConnection.IsOpen() )
{
if ( pSql[i].bUse && pSql[i].lRandID>0 ) //在使用中的SQL,40分钟超时
{
if ( dwNow - pSql[i].dwEndUse > SQL_TIMEOUT_USE )
{
pSql[i].adoConnection.Close();
pSql[i].bUse = false;
pSql[i].lRandID = 0;
_stprintf(szMsg, _T("SQL:%d 操作超时,自动断连!") , i );
m_pDlg->AddLog(szMsg);
}
}
else
{
//不在使用中的SQL,20分钟超时
if ( dwNow - pSql[i].dwEndUse > SQL_TIMEOUT_DISUSE )
{
pSql[i].adoConnection.Close();
pSql[i].bUse = false;
pSql[i].lRandID = 0;
_stprintf(szMsg, _T("SQL:%d 超时未使用,自动断连!") , i );
m_pDlg->AddLog(szMsg);
}
}
}
}
}
}
catch (...)
{
LOG_APPERROR(_T("T"));
}
}
DWORD WINAPI CIOCP::MainLoop2(LPVOID lp_param)
{
try
{
AutoCoInitializeEx AutoCoInit; //自动初始化与结束Com环境
CIOCP * piocp = (CIOCP *)lp_param;
int nCount = 0;
int nCount2= 0;
while( !piocp->m_bQuit )
{
nCount ++;
if ( nCount>10 ) //每5秒检测一次超时
{
nCount=0;
piocp->CheckForInvalidConnection();
}
nCount2 ++;
if ( nCount2>120 ) //每1分钟检测一次超时
{
nCount2=0;
piocp->CheckForInvalidSQLConnection();
}
Sleep(500);
}
return TRUE;
}
catch(...)
{
LOG_APPERROR(_T("T"));
return false;
}
}