socket服务器:实现1对N可配置Socket服务器程序思路来源: 发布时间:星期四, 2009年2月12日 浏览:64次 评论:0
大致思路:框架是MFC单文档, 从CSocket派生个CListen类然后在Doc类:CWebDoc中OnNewDocument中个CListen对象将该对象指针保存到文档类成员m_pSocket中并把文档指针传递给CListen类: m_pSocket = CListen ( this ) ; OnNewDocument接着CListenCreate: m_pSocket->Create ( theApp.m_wwwPort ); OnNewDocument接着CListenListen开始监听服务器m_wwwPort端口: m_pSocket->Listen; 当服务器m_wwwPort端口侦听到连接请求时CListen类OnAccept重载会被在CListen类OnAccept中我们在Doc类中自建个OnAccept void CListen::OnAccept( nErrorCode) { CSocket::OnAccept(nErrorCode); m_pDoc->OnAccept ; // process this in the context of the document } 显然旦某个客户连接请求到来我们在Doc类中自建OnAccept马上被代码如上Doc类OnAccept马上个CClient并把文档指针传递给CClient类: CClient *pClient = CClient ( this ) ; 接下来用CListen指针m_pSocket来Accept并把刚刚CClient对象作为参数: m_pSocket->Accept ( *pClient ); 如无意外个套接字连接就建立了服务器要1对N服务为了维护这些连接我们在文档类增加了个CPtrList成员:m_listConnects; 连接旦建立立即测试当前m_listConnects中已有连接数是否已经达到最大连接限制: ( m_listConnects.GetCount >= ()theApp.m_nMaxConnects ) { // 友好提示客户服务器已经满载请稍后再试 pClient->SendCannedMsg ( 503 ) ; delete pClient; } 当然如果连接List还没有满载马上m_listConnectsAddTail把CClient指针加进指针链表成员中以便后来 服务器和各客户收发报文使用 在CClientOnReceive中我们接受客户发来数据并分析数据处理数据完后发送响应报文: void CClient::OnReceive( nErrorCode) { CSocket::OnReceive(nErrorCode); DWORD dwBytes ; IOCtl ( FIONREAD, &dwBytes ) ; // anything to get? ( dwBytes 0 ) ( TRUE ) ; // we must be done! * buf = (*)malloc ( dwBytes ) ( Receive ( buf, dwBytes, 0 ) ) ProcessReq; } 在CClientOnClose中我们可以记载客户关闭套接字事件: void CClient::OnClose( nErrorCode) { CSocket::OnClose(nErrorCode); m_pDoc->Message ( "OnClose::\n" ) ; } 为了及时关闭和释放那些长期不活动客户连接CClient类维护了个LOG_RECORD成员m_LogRec记载了其相关信息例举个LOG_RECORD结构大致如下: typedef struct { CString client ; // 客户机器IP或名称 CTime datetime ; // 最后报文发送时间 LONG reqID; // 最后报文请求ID ...... } LOG_RECORD, *LPLOG_RECORD; 在CMainFrame类开启个Timer以1分钟为间隔定期清理释放不活跃客户: CXXXDoc* pDoc = (CXXXDoc*)GetActiveDocument ; pDoc->CheckIdleConnects ; 在文档类CheckIdleConnects中: time_t tNow ; time( &tNow ) ; CTime cNow ( tNow ) ; CTimeSpan cTimeOut ( 0, 0, 0, theApp.m_nTimeOut ) ; cNow -= cTimeOut ; for ( POSITION pos = m_listConnects.GetHeadPosition ; pos != NULL ; ) { CClient* pClient = (CClient*)m_listConnects.GetNext ( pos ) ; ( pClient->m_LogRec.datetime < cNow ) { m_listConnects.RemoveAt ( pos ) ; delete pClient; } } by Loomman, QQ:28077188, MSN: [email protected] QQ裙:30515563 天堂 请尊重作者原创转载注明来自裂帛剑博客谢谢合作 0
相关文章读者评论发表评论 |