对 IOCP Content 大家是怎么管理的? 希望听听行家的建议。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 struct _IO_CONTEXT{WSAOVERLAPPED ol; // 重叠结构WSABUF wsaBuffer; // WSASend/WSARecv使用的缓冲区SOCKET sClient; // 客户端套接字DWORD dwBytesSent; // 已经发送的字节数DWORD dwBytesRecv; // 已经接收的字节数DWORD dwIoFlag; // IO标志char szBuffer[BUFFER_SIZE]; // 接收数据的缓冲区};int nResult = 0;DWORD dwIosize = 0;DWORD dwFlags = 0;ZeroMemory(&lpIoContext->ol, sizeof(WSAOVERLAPPED));nResult = WSARecv(lpIoContext->sClient,&lpIoContext->wsaBuffer,1,&dwIosize,&dwFlags,&lpIoContext->ol,NULL);if((nResult==SOCKET_ERROR) && (WSAGetLastError()!=WSA_IO_PENDING)){ return FALSE;}return TRUE; lpIoContext就是一个new出来的_IO_CONTEXT, 当你要同时提交多个WSASend或者多个WSARecv的时候,为每一个WSASend或者WSARecv新new一个lpIoContext就行了。提供比较完整的代码:bool CIOCPServerTCP::InitializeIOCP(){DWORD i;DWORD nThreadID;SYSTEM_INFO systemInfo;// 创建完成端口SOCKET s;s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);if ( s == INVALID_SOCKET ) return false;m_hIOCP = CreateIoCompletionPort( (HANDLE)s, NULL, 0, 0 );if ( m_hIOCP == NULL ) {closesocket( s );return false;}// Close the socket, we don't need it any longer.closesocket( s );// create the work thread// Determine how many processors are on the system.GetSystemInfo( &systemInfo );m_ProcessorNum = (short) systemInfo.dwNumberOfProcessors;UINT nWorkerCnt = m_ProcessorNum * 2;// We need to save the Handles for Later TerminationHANDLE hWorker = NULL;for ( i = 0; i < nWorkerCnt; i++ ) {hWorker = (HANDLE)CreateThread( NULL, 0,// Stack size - use defaultThreadPoolFunc, // Thread fn entry point(void*) this, // Param for thread0, // Init flag&nThreadID); // Thread addressif (hWorker == NULL ) {return false;}CloseHandle(hWorker);}return true;}bool CIOCPServerTCP::CreateListenSocket(){int nRet;m_SocketListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);if (m_SocketListen == INVALID_SOCKET){return false;}// bind the serverSOCKADDR_IN saServer; saServer.sin_family = AF_INET;saServer.sin_port = htons(m_nPort);saServer.sin_addr.s_addr = INADDR_ANY;// bind our name to the socketnRet = bind( m_SocketListen, (LPSOCKADDR)&saServer, sizeof(struct sockaddr) );if (nRet == SOCKET_ERROR){closesocket(m_SocketListen);return false;}// Set the socket to listennRet = listen(m_SocketListen, m_MaxConnections);if (nRet == SOCKET_ERROR){closesocket(m_SocketListen);return false;}// beging the listening threadDWORD dwThreadId = 0;m_hThread = (HANDLE)CreateThread( NULL, // Security0, // Stack size - use defaultListenThreadProc, // Thread fn entry point(void*) this, 0, // Init flag&dwThreadId); // Thread addressif (m_hThread == INVALID_HANDLE_VALUE){return false;}return true;}DWORD WINAPI CIOCPServerTCP::ListenThreadProc( LPVOID lpVoid ){int nRet=0;CIOCPServerTCP* pThis = reinterpret_cast<CIOCPServerTCP*>(lpVoid);SIOCPPerSocketTCPContext* lpPerSocketContext = NULL;SOCKET SocketAccept = INVALID_SOCKET;DWORD dwRecvNumBytes, dwFlags=MSG_PARTIAL;while( TRUE ) {// Loop forever accepting connections from clients // until console shuts down.SocketAccept = WSAAccept(pThis->m_SocketListen, NULL, NULL, NULL, 0);if( SocketAccept == SOCKET_ERROR ) {return -1;}// we add the just returned socket descriptor to // the IOCP along with its associated key data.// also added context structures to a global list.lpPerSocketContext = pThis->UpdateCompletionPort(SocketAccept, IOCPIORead, TRUE);if( lpPerSocketContext == NULL )return -1;// post initial receive on this socketnRet = WSARecv( SocketAccept, &(lpPerSocketContext->IOContext.wsaInBuf), 1, &dwRecvNumBytes, &dwFlags,&(lpPerSocketContext->IOContext.Overlapped),NULL );int error = WSAGetLastError();if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {pThis->ClientContentClose( lpPerSocketContext, FALSE );}} //whilereturn 0;}DWORD WINAPI CIOCPServerTCP::ThreadPoolFunc( LPVOID WorkContext ){CIOCPServerTCP* pThis = reinterpret_cast<CIOCPServerTCP*>(WorkContext);HANDLE hIOCP = pThis->m_hIOCP;SIOCPPerSocketTCPContext* lpPerSocketContext = NULL;SIOCPPerIoTCPContext* llpIOContext = NULL;LPWSAOVERLAPPED lpOverlapped = NULL;SPacketServerRecvTCP* lpPacketTCPTemp = NULL;BOOL bSuccess = FALSE;int nRet = 0;DWORD dwRecvNumBytes = 0;DWORD dwSendNumBytes = 0;DWORD dwFlags = 0;DWORD dwIoSize = 0;uint4 nDataSize=0;SPacketServerRecvTCP *lpPacketTCP=NULL;while( true ) {// continually loop to service io completion packetsbSuccess = GetQueuedCompletionStatus( hIOCP, &dwIoSize,(LPDWORD) &lpPerSocketContext,if( !lpPerSocketContext ) continue;// determine what type of IO packet has completedllpIOContext = (SIOCPPerIoTCPContext*)lpOverlapped;if( !llpIOContext ) continue;switch( llpIOContext->IOOperation ) {// a read operation has completedcase IOCPIORead:// 注意,连接突然中断时要从等待接收队列中去除该等待项if( dwIoSize == 0 ){// 去除该等待项并关闭连接pThis->m_pTCPSocketIDToPacketRecvTCPMapWait->RemoveKey( lpPacketTCPTemp->nSocketID );pThis->ClientContentClose( lpPerSocketContext, FALSE );continue;} // 接收数据处理// continue to recvnRet = WSARecv( lpPerSocketContext->Socket, &(lpPerSocketContext->IOContext.wsaInBuf), 1, &dwRecvNumBytes, &dwFlags,&(lpPerSocketContext->IOContext.Overlapped),NULL );if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {// 关闭连接pThis->ClientContentClose(lpPerSocketContext, FALSE);}break;// a write operation has completedcase IOCPIOWrite:if( dwIoSize <= 0 ){// 释放内存if( lpPerSocketContext->IOContext.wsaOutBuf.buf ){// 释放发送空间pThis->m_pMemoryPoolLinearMul->PutMem( lpPerSocketContext->IOContext.wsaOutBuf.buf, lpPerSocketContext->IOContext.wsaOutBuf.len );}if( nRet != 0 ){// 去除该等待项pThis->m_pTCPSocketIDToPacketRecvTCPMapWait->RemoveKey( lpPacketTCPTemp->nSocketID );}// 关闭连接pThis->ClientContentClose( lpPerSocketContext, FALSE );continue;}else{// 发送完成}break;default:break;} //switch} //whilereturn 0;}SIOCPPerSocketTCPContext* CIOCPServerTCP::UpdateCompletionPort(SOCKET sd, IOCP_IO_OPERATION ClientIo, BOOL bAddToList) {SIOCPPerSocketTCPContext* lpPerSocketTCPContext = NULL;lpPerSocketTCPContext = ClientContentAlloc(sd, ClientIo);if( lpPerSocketTCPContext == NULL )return(NULL);// 初始化设备上下文ZeroMemory( lpPerSocketTCPContext, sizeof(SIOCPPerSocketTCPContext) );// 将连接的socket与对应的设备上下文与完成端口句柄关联起来。HANDLE hIOCPTemp = NULL;hIOCPTemp = CreateIoCompletionPort( (HANDLE)sd, m_hIOCP, (DWORD )lpPerSocketTCPContext, 0 );if( !hIOCPTemp ) {ClientContentFree( lpPerSocketTCPContext );return (NULL);}// 获得TCP连接的唯一编号bool bContinue = true;int nSocketID = 0;SIOCPPerSocketTCPContext* lpTempContext;while( bContinue ){nSocketID = m_rSysCoreServerStatus.GetTCPSocketID();bContinue = m_pTCPSocketIDToTCPContextMap->Lookup( nSocketID, lpTempContext );}lpPerSocketTCPContext->nSocketID = nSocketID;lpPerSocketTCPContext->Socket = sd;lpPerSocketTCPContext->IOContext.wsaInBuf.buf = lpPerSocketTCPContext->IOContext.szBuffer;lpPerSocketTCPContext->IOContext.wsaInBuf.len = sizeof( lpPerSocketTCPContext->IOContext.szBuffer );lpPerSocketTCPContext->IOContext.IOOperation = IOCPIORead;// 将其加入TCP连接编号与设备上下文映射if( bAddToList ) m_pTCPSocketIDToTCPContextMap->SetAt( lpPerSocketTCPContext->nSocketID, lpPerSocketTCPContext );return lpPerSocketTCPContext;}// Close down a connection with a client.bool CIOCPServerTCP::ClientContentClose ( SIOCPPerSocketTCPContext* lpPerSocketContext,BOOL bGraceful ) {// 取消所有IO操作CancelIo( (HANDLE)lpPerSocketContext->Socket);// 从客户连接链表中删除该项m_pTCPSocketIDToTCPContextMap->RemoveKey( lpPerSocketContext->nSocketID );// 关闭连接closesocket( lpPerSocketContext->Socket );lpPerSocketContext->Socket = INVALID_SOCKET;// 释放内存ClientContentFree( lpPerSocketContext );return true;} // 客户信息结构分配SIOCPPerSocketTCPContext* CIOCPServerTCP::ClientContentAlloc(SOCKET sd, IOCP_IO_OPERATION ClientIO){SIOCPPerSocketTCPContext* lpTemp = new SIOCPPerSocketTCPContext(); memset( lpTemp, 0, sizeof(SIOCPPerSocketTCPContext) );return lpTemp;} MFC中一个视图分为两部分,加载两幅位图 MFC应用程序可以调用用WIN32应用程序向导建立的动态库么 DrawText 多行显示怎样设置间距? 有什么可以解释在类的成员函数内无法访问类的成员变量? vc中odbc连接sql server后,添加新记录时出现错误?导致推出程序,详情请看内容,急。。。。在线等 关于COM中的类型转换问题 请问如何用VC获得机器的CPU ID。 CComboBox中的分隔符是什么? 问个关于数据库操作的出错"error LNK2005:"详细在贴中 顶级问题。。。。。。VC 系统 DEBUG ? 80分求源码 诸位同好:用Dialog取得的信息通常如何保存?
{
WSAOVERLAPPED ol; // 重叠结构
WSABUF wsaBuffer; // WSASend/WSARecv使用的缓冲区
SOCKET sClient; // 客户端套接字
DWORD dwBytesSent; // 已经发送的字节数
DWORD dwBytesRecv; // 已经接收的字节数
DWORD dwIoFlag; // IO标志
char szBuffer[BUFFER_SIZE]; // 接收数据的缓冲区
};
int nResult = 0;
DWORD dwIosize = 0;
DWORD dwFlags = 0;
ZeroMemory(&lpIoContext->ol, sizeof(WSAOVERLAPPED));
nResult = WSARecv(
lpIoContext->sClient,
&lpIoContext->wsaBuffer,
1,
&dwIosize,
&dwFlags,
&lpIoContext->ol,
NULL
);
if((nResult==SOCKET_ERROR) && (WSAGetLastError()!=WSA_IO_PENDING))
{
return FALSE;
}return TRUE;
lpIoContext就是一个new出来的_IO_CONTEXT, 当你要同时提交多个WSASend或者多个WSARecv的时候,为每一个WSASend或者WSARecv新new一个lpIoContext就行了。提供比较完整的代码:bool CIOCPServerTCP::InitializeIOCP()
{
DWORD i;
DWORD nThreadID;
SYSTEM_INFO systemInfo;// 创建完成端口
SOCKET s;s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if ( s == INVALID_SOCKET )
return false;m_hIOCP = CreateIoCompletionPort( (HANDLE)s, NULL, 0, 0 );
if ( m_hIOCP == NULL )
{
closesocket( s );
return false;
}
// Close the socket, we don't need it any longer.
closesocket( s );// create the work thread
// Determine how many processors are on the system.
GetSystemInfo( &systemInfo );
m_ProcessorNum = (short) systemInfo.dwNumberOfProcessors;
UINT nWorkerCnt = m_ProcessorNum * 2;// We need to save the Handles for Later Termination
HANDLE hWorker = NULL;for ( i = 0; i < nWorkerCnt; i++ )
{
hWorker = (HANDLE)CreateThread( NULL, 0,// Stack size - use default
ThreadPoolFunc, // Thread fn entry point
(void*) this, // Param for thread
0, // Init flag
&nThreadID); // Thread address
if (hWorker == NULL )
{
return false;
}
CloseHandle(hWorker);
}return true;
}bool CIOCPServerTCP::CreateListenSocket()
{
int nRet;m_SocketListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (m_SocketListen == INVALID_SOCKET)
{
return false;
}// bind the server
SOCKADDR_IN saServer; saServer.sin_family = AF_INET;
saServer.sin_port = htons(m_nPort);
saServer.sin_addr.s_addr = INADDR_ANY;// bind our name to the socket
nRet = bind( m_SocketListen,
(LPSOCKADDR)&saServer,
sizeof(struct sockaddr) );
if (nRet == SOCKET_ERROR)
{
closesocket(m_SocketListen);
return false;
}// Set the socket to listen
nRet = listen(m_SocketListen, m_MaxConnections);
if (nRet == SOCKET_ERROR)
{
closesocket(m_SocketListen);
return false;
}// beging the listening thread
DWORD dwThreadId = 0;m_hThread = (HANDLE)CreateThread( NULL, // Security
0, // Stack size - use default
ListenThreadProc, // Thread fn entry point
(void*) this,
0, // Init flag
&dwThreadId); // Thread address
if (m_hThread == INVALID_HANDLE_VALUE)
{
return false;
}return true;
}DWORD WINAPI CIOCPServerTCP::ListenThreadProc( LPVOID lpVoid )
{
int nRet=0;
CIOCPServerTCP* pThis = reinterpret_cast<CIOCPServerTCP*>(lpVoid);SIOCPPerSocketTCPContext* lpPerSocketContext = NULL;
SOCKET SocketAccept = INVALID_SOCKET;DWORD dwRecvNumBytes, dwFlags=MSG_PARTIAL;while( TRUE )
{
// Loop forever accepting connections from clients
// until console shuts down.
SocketAccept = WSAAccept(pThis->m_SocketListen, NULL,
NULL, NULL, 0);
if( SocketAccept == SOCKET_ERROR )
{
return -1;
}// we add the just returned socket descriptor to
// the IOCP along with its associated key data.
// also added context structures to a global list.
lpPerSocketContext = pThis->UpdateCompletionPort(SocketAccept,
IOCPIORead, TRUE);
if( lpPerSocketContext == NULL )
return -1;// post initial receive on this socket
nRet = WSARecv( SocketAccept,
&(lpPerSocketContext->IOContext.wsaInBuf),
1, &dwRecvNumBytes, &dwFlags,
&(lpPerSocketContext->IOContext.Overlapped),
NULL );int error = WSAGetLastError();
if( nRet == SOCKET_ERROR
&& (ERROR_IO_PENDING != WSAGetLastError()) )
{
pThis->ClientContentClose( lpPerSocketContext, FALSE );
}
} //whilereturn 0;
}DWORD WINAPI CIOCPServerTCP::ThreadPoolFunc( LPVOID WorkContext )
{
CIOCPServerTCP* pThis = reinterpret_cast<CIOCPServerTCP*>(WorkContext);
HANDLE hIOCP = pThis->m_hIOCP;SIOCPPerSocketTCPContext* lpPerSocketContext = NULL;
SIOCPPerIoTCPContext* llpIOContext = NULL;
LPWSAOVERLAPPED lpOverlapped = NULL;SPacketServerRecvTCP* lpPacketTCPTemp = NULL;BOOL bSuccess = FALSE;
int nRet = 0;DWORD dwRecvNumBytes = 0;
DWORD dwSendNumBytes = 0;
DWORD dwFlags = 0;
DWORD dwIoSize = 0;uint4 nDataSize=0;
SPacketServerRecvTCP *lpPacketTCP=NULL;
while( true )
{
// continually loop to service io completion packets
bSuccess = GetQueuedCompletionStatus( hIOCP, &dwIoSize,
(LPDWORD) &lpPerSocketContext,
if( !lpPerSocketContext )
continue;// determine what type of IO packet has completed
llpIOContext = (SIOCPPerIoTCPContext*)lpOverlapped;
if( !llpIOContext )
continue;switch( llpIOContext->IOOperation )
{
// a read operation has completed
case IOCPIORead:
// 注意,连接突然中断时要从等待接收队列中去除该等待项
if( dwIoSize == 0 )
{
// 去除该等待项并关闭连接
pThis->m_pTCPSocketIDToPacketRecvTCPMapWait->RemoveKey( lpPacketTCPTemp->nSocketID );
pThis->ClientContentClose( lpPerSocketContext, FALSE );
continue;
}
// 接收数据处理// continue to recv
nRet = WSARecv( lpPerSocketContext->Socket,
&(lpPerSocketContext->IOContext.wsaInBuf),
1, &dwRecvNumBytes, &dwFlags,
&(lpPerSocketContext->IOContext.Overlapped),
NULL );
if( nRet == SOCKET_ERROR
&& (ERROR_IO_PENDING != WSAGetLastError()) )
{
// 关闭连接
pThis->ClientContentClose(lpPerSocketContext, FALSE);
}
break;
// a write operation has completed
case IOCPIOWrite:if( dwIoSize <= 0 )
{
// 释放内存
if( lpPerSocketContext->IOContext.wsaOutBuf.buf )
{
// 释放发送空间
pThis->m_pMemoryPoolLinearMul->PutMem( lpPerSocketContext->IOContext.wsaOutBuf.buf,
lpPerSocketContext->IOContext.wsaOutBuf.len );
}
if( nRet != 0 )
{
// 去除该等待项
pThis->m_pTCPSocketIDToPacketRecvTCPMapWait->RemoveKey( lpPacketTCPTemp->nSocketID );
}
// 关闭连接
pThis->ClientContentClose( lpPerSocketContext, FALSE );
continue;
}
else
{
// 发送完成}break;default:
break;
} //switch
} //whilereturn 0;
}SIOCPPerSocketTCPContext* CIOCPServerTCP::UpdateCompletionPort(SOCKET sd,
IOCP_IO_OPERATION ClientIo, BOOL bAddToList)
{
SIOCPPerSocketTCPContext* lpPerSocketTCPContext = NULL;lpPerSocketTCPContext = ClientContentAlloc(sd, ClientIo);
if( lpPerSocketTCPContext == NULL )
return(NULL);// 初始化设备上下文
ZeroMemory( lpPerSocketTCPContext, sizeof(SIOCPPerSocketTCPContext) );// 将连接的socket与对应的设备上下文与完成端口句柄关联起来。
HANDLE hIOCPTemp = NULL;
hIOCPTemp = CreateIoCompletionPort( (HANDLE)sd,
m_hIOCP, (DWORD )lpPerSocketTCPContext, 0 );
if( !hIOCPTemp )
{
ClientContentFree( lpPerSocketTCPContext );
return (NULL);
}// 获得TCP连接的唯一编号
bool bContinue = true;
int nSocketID = 0;
SIOCPPerSocketTCPContext* lpTempContext;
while( bContinue )
{
nSocketID = m_rSysCoreServerStatus.GetTCPSocketID();
bContinue = m_pTCPSocketIDToTCPContextMap->Lookup( nSocketID, lpTempContext );
}lpPerSocketTCPContext->nSocketID = nSocketID;
lpPerSocketTCPContext->Socket = sd;
lpPerSocketTCPContext->IOContext.wsaInBuf.buf = lpPerSocketTCPContext->IOContext.szBuffer;
lpPerSocketTCPContext->IOContext.wsaInBuf.len = sizeof( lpPerSocketTCPContext->IOContext.szBuffer );
lpPerSocketTCPContext->IOContext.IOOperation = IOCPIORead;// 将其加入TCP连接编号与设备上下文映射
if( bAddToList )
m_pTCPSocketIDToTCPContextMap->SetAt( lpPerSocketTCPContext->nSocketID, lpPerSocketTCPContext );return lpPerSocketTCPContext;
}// Close down a connection with a client.
bool CIOCPServerTCP::ClientContentClose ( SIOCPPerSocketTCPContext* lpPerSocketContext,
BOOL bGraceful )
{
// 取消所有IO操作
CancelIo( (HANDLE)lpPerSocketContext->Socket);// 从客户连接链表中删除该项
m_pTCPSocketIDToTCPContextMap->RemoveKey( lpPerSocketContext->nSocketID );// 关闭连接
closesocket( lpPerSocketContext->Socket );
lpPerSocketContext->Socket = INVALID_SOCKET;// 释放内存
ClientContentFree( lpPerSocketContext );return true;
} // 客户信息结构分配
SIOCPPerSocketTCPContext* CIOCPServerTCP::ClientContentAlloc(SOCKET sd,
IOCP_IO_OPERATION ClientIO)
{
SIOCPPerSocketTCPContext* lpTemp = new SIOCPPerSocketTCPContext();
memset( lpTemp, 0, sizeof(SIOCPPerSocketTCPContext) );
return lpTemp;
}