posts - 94, comments - 250, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

奇迹世界服务器架构(4)

Posted on 2009-01-01 15:26 Condor 阅读(1917) 评论(1)  编辑 收藏 引用

未获取函数指针就调用函数(如直接连接mswsock..lib并直接调用AcceptEx)的消耗是很大的,因为AcceptEx 实际上是存在于Winsock2结构体系之外的。每次应用程序常试在服务提供层上(mswsock之上)调用AcceptEx时,都要先通过WSAIoctl获取该函数指针。如果要避免这个很影响性能的操作,应用程序最好是直接从服务提供层通过WSAIoctl先获取这些APIs的指针。  

奇迹世界 network 类里面就进行指针获取

void MsWinsockUtil::LoadExtensionFunction( SOCKET ActiveSocket )
{
//AcceptEx 窃荐 啊廉坷扁 (dll俊辑..)
GUID acceptex_guid = WSAID_ACCEPTEX;
LoadExtensionFunction( ActiveSocket, acceptex_guid, (void**) &m_lpfnAccepteEx);

//TransmitFile 窃荐 啊廉坷扁 (dll俊辑..)
GUID transmitfile_guid = WSAID_TRANSMITFILE;
LoadExtensionFunction( ActiveSocket, transmitfile_guid, (void**) &m_lpfnTransmitFile);

//GetAcceptExSockaddrs 窃荐 啊廉坷扁
GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
LoadExtensionFunction( ActiveSocket, guidGetAcceptExSockaddrs, (void**) &m_lpfnGetAcceptExSockAddrs);

//DisconnectEx 窃荐 啊廉坷扁
GUID guidDisconnectEx = WSAID_DISCONNECTEX;
LoadExtensionFunction( ActiveSocket, guidDisconnectEx, (void**) &m_lpfnDisconnectEx );
}

bool MsWinsockUtil::LoadExtensionFunction( SOCKET ActiveSocket, GUID FunctionID, void **ppFunc )
{
DWORD dwBytes = 0;

if (0 != WSAIoctl(
   ActiveSocket,
   SIO_GET_EXTENSION_FUNCTION_POINTER,
   &FunctionID,
   sizeof(GUID),
   ppFunc,
   sizeof(void *),
   &dwBytes,
   0,
   0))
{
   return false;
}

return true;
}

LPFN_ACCEPTEX     MsWinsockUtil::m_lpfnAccepteEx     = NULL;
LPFN_TRANSMITFILE    MsWinsockUtil::m_lpfnTransmitFile    = NULL;
LPFN_GETACCEPTEXSOCKADDRS MsWinsockUtil::m_lpfnGetAcceptExSockAddrs = NULL;
LPFN_DISCONNECTEX    MsWinsockUtil::m_lpfnDisconnectEx    = NULL;

 

收包和发包循环:

服务器需要进行的连接如下:

1、 与其他服务器连接

2、监听绑定端口

这个2个内容都封装进SESSION内里面,通过NETWORKOBJECT对象判断该进行哪部分的包处理

if( !pIOCPServer->Init( &desc, 1 ) )
根据参数&desc ,对完成端口进行设置

内容有:创建 io_thread(工作者线程), accept_thread(绑定端口),connect_thread(连接其他服务器), send_thread(收包线程),并根据连接的最大数目分配好session pool。

if( !pIOCPServer->StartListen( CLIENT_IOHANDLER_KEY, "127.0.0.1", 6000 ) )
{
   printf( "监听出错" );
   return 0;
}

pIOCPServer->Connect( CLIENT_IOHANDLER_KEY, pNetObj, "127.0.0.1", 7000 );

收包:

pIOCPServer->Update()      ---------》 IOHANDLER_MAP_ITER it->second->Update()    ----------》

VOID IoHandler::Update()
{
ProcessActiveSessionList();

if( !m_pAcceptedSessionList->empty() )
{
   ProcessAcceptedSessionList();
}

if( !m_pConnectSuccessList->empty() )
{
   ProcessConnectSuccessList();
}

if( !m_pConnectFailList->empty() )
{
   ProcessConnectFailList();
}

KickDeadSessions();
}   

收包循环

    if( !pSession->ProcessRecvdPacket( m_dwMaxPacketSize ) )
    {
     pSession->Remove();
    }

发包循环

unsigned __stdcall send_thread( LPVOID param )
{
IOCPServer *pIOCPServer = (IOCPServer*)param;
IOHANDLER_MAP_ITER it;
while( !pIOCPServer->m_bShutdown )
{
   Sleep( 10 );

   for( it = pIOCPServer->m_mapIoHandlers.begin(); it != pIOCPServer->m_mapIoHandlers.end(); ++it )
   {
    it->second->ProcessSend();
   }
}

return 0;
}

Feedback

# re: 奇迹世界服务器架构(4)[未登录]  回复  更多评论   

2009-01-01 21:09 by 关中刀客
看起来确实不怎么样。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理