专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »C 教程 » socket服务器:实现1对N可配置Socket服务器程序思路 »正文

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

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: