1。框架介绍
http://iunknown.javaeye.com/blog/59804
2。源码分析
下文源码分析基于最新源码0.9.5,下载地址http://code.google.com/p/spserver/downloads/list
3。主程序
SP_Server的调用链条是runForever()->eventLoop()->start()
start()中有如下方法
acceptArg.mEventArg = &eventArg;
acceptArg.mHandlerFactory = mHandlerFactory;
acceptArg.mIOChannelFactory = mIOChannelFactory;
acceptArg.mReqQueueSize = mReqQueueSize;
acceptArg.mMaxConnections = mMaxConnections;
acceptArg.mRefusedMsg = mRefusedMsg;
struct event evAccept;
event_set( &evAccept, listenFD, EV_READ|EV_PERSIST,
SP_EventCallback::onAccept, &acceptArg );
event_base_set( eventArg.getEventBase(), &evAccept );
event_add( &evAccept, NULL );
结合libevent我们可以看出,这里是将服务器的socket(listenFD)和EV_READ事件注册到libevent当中
当有客户端连入时,去找SP_EventCallback::onAccept去处理
转入到SP_EventCallback::onAccept 当中,可以注意到如下关键代码
void SP_EventCallback :: onAccept( int fd, short events, void * arg )
{
int clientFD;
struct sockaddr_in addr;
socklen_t addrLen = sizeof( addr );
SP_AcceptArg_t * acceptArg = (SP_AcceptArg_t*)arg;
SP_EventArg * eventArg = acceptArg->mEventArg;
clientFD = accept( fd, (struct sockaddr *)&addr, &addrLen );
if( -1 == clientFD ) {
sp_syslog( LOG_WARNING, "accept failed" );
return;
}
if( SP_IOUtils::setNonblock( clientFD ) < 0 ) {
sp_syslog( LOG_WARNING, "failed to set client socket non-blocking" );
}
SP_Sid_t sid;
sid.mKey = eventArg->getSessionManager()->allocKey( &sid.mSeq );
assert( sid.mKey > 0 );
SP_Session * session = new SP_Session( sid );
char strip[ 32 ] = { 0 };
SP_IOUtils::inetNtoa( &( addr.sin_addr ), strip, sizeof( strip ) );
session->getRequest()->setClientIP( strip );
session->getRequest()->setClientPort( ntohs( addr.sin_port ) );
if( 0 == getsockname( clientFD, (struct sockaddr*)&addr, &addrLen ) ) {
SP_IOUtils::inetNtoa( &( addr.sin_addr ), strip, sizeof( strip ) );
session->getRequest()->setServerIP( strip );
}
if( NULL != session ) {
eventArg->getSessionManager()->put( sid.mKey, sid.mSeq, session );
session->setHandler( acceptArg->mHandlerFactory->create() );
session->setIOChannel( acceptArg->mIOChannelFactory->create() );
session->setArg( eventArg );
event_set( session->getReadEvent(), clientFD, EV_READ, onRead, session );
event_set( session->getWriteEvent(), clientFD, EV_WRITE, onWrite, session );
if( eventArg->getSessionManager()->getCount() > acceptArg->mMaxConnections
|| eventArg->getInputResultQueue()->getLength() >= acceptArg->mReqQueueSize ) {
sp_syslog( LOG_WARNING, "System busy, session.count %d [%d], queue.length %d [%d]",
eventArg->getSessionManager()->getCount(), acceptArg->mMaxConnections,
eventArg->getInputResultQueue()->getLength(), acceptArg->mReqQueueSize );
SP_Message * msg = new SP_Message();
msg->getMsg()->append( acceptArg->mRefusedMsg );
msg->getMsg()->append( "/r/n" );
session->getOutList()->append( msg );
session->setStatus( SP_Session::eExit );
addEvent( session, EV_WRITE, clientFD );
} else {
SP_EventHelper::doStart( session );
}
} else {
eventArg->getSessionManager()->remove( sid.mKey, sid.mSeq );
sp_close( clientFD );
sp_syslog( LOG_WARNING, "Out of memory, cannot allocate session object!" );
}
}
有上述分析,可以看到accept收到了clientFD,然后创建session,由event_set对clientFD和session进行封装,当clientFD产生EV_READ(有数据传入服务器)时调用onRead,当clientFD产生EV_WRITE(数据可以发送)调用onWrite.
.....未完待续