提交 d605d7a5623b1095fd7ce8d58c32394afc36d163

作者 LJH 李佳桓
1 个父辈 c7d31adc

add

正在显示 1 个修改的文件 包含 329 行增加0 行删除
  1 +/*
  2 + * Copyright 2008 Stephen Liu
  3 + * For license terms, see the file COPYING along with this library.
  4 + */
  5 +
  6 +#include <winsock2.h>
  7 +#include <windows.h>
  8 +#include <stdio.h>
  9 +#include <assert.h>
  10 +
  11 +#include "spthread.hpp"
  12 +
  13 +#define _CRTDBG_MAP_ALLOC
  14 +#include <stdlib.h>
  15 +#include <crtdbg.h>
  16 +
  17 +#include "spporting.hpp"
  18 +#include "spwin32iocp.hpp"
  19 +#include "spiocpserver.hpp"
  20 +
  21 +#include "spmsgdecoder.hpp"
  22 +#include "spbuffer.hpp"
  23 +
  24 +#include "sphandler.hpp"
  25 +#include "spresponse.hpp"
  26 +#include "sprequest.hpp"
  27 +#include "sputils.hpp"
  28 +
  29 +#pragma comment(lib,"ws2_32")
  30 +#pragma comment(lib,"mswsock")
  31 +
  32 +class SP_OnlineSidList {
  33 +public:
  34 + SP_OnlineSidList();
  35 + ~SP_OnlineSidList();
  36 +
  37 + void copy( SP_SidList * outList, SP_Sid_t * ignoreSid = NULL );
  38 + void remove( SP_Sid_t sid );
  39 + void add( SP_Sid_t sid );
  40 + int getCount();
  41 +
  42 +private:
  43 + SP_SidList mList;
  44 + sp_thread_mutex_t mMutex;
  45 +};
  46 +
  47 +SP_OnlineSidList :: SP_OnlineSidList()
  48 +{
  49 + sp_thread_mutex_init( &mMutex, NULL );
  50 +}
  51 +
  52 +SP_OnlineSidList :: ~SP_OnlineSidList()
  53 +{
  54 + sp_thread_mutex_destroy( &mMutex );
  55 +}
  56 +
  57 +void SP_OnlineSidList :: copy( SP_SidList * outList, SP_Sid_t * ignoreSid )
  58 +{
  59 + sp_thread_mutex_lock( &mMutex );
  60 +
  61 + for( int i = 0; i < mList.getCount(); i++ ) {
  62 + if( NULL != ignoreSid ) {
  63 + SP_Sid_t theSid = mList.get( i );
  64 + if( theSid.mKey == ignoreSid->mKey && theSid.mSeq == ignoreSid->mSeq ) {
  65 + continue;
  66 + }
  67 + }
  68 +
  69 + outList->add( mList.get( i ) );
  70 + }
  71 +
  72 + sp_thread_mutex_unlock( &mMutex );
  73 +}
  74 +
  75 +void SP_OnlineSidList :: remove( SP_Sid_t sid )
  76 +{
  77 + sp_thread_mutex_lock( &mMutex );
  78 +
  79 + for( int i = 0; i < mList.getCount(); i++ ) {
  80 + SP_Sid_t theSid = mList.get( i );
  81 + if( theSid.mKey == sid.mKey && theSid.mSeq == sid.mSeq ) {
  82 + mList.take( i );
  83 + break;
  84 + }
  85 + }
  86 +
  87 + sp_thread_mutex_unlock( &mMutex );
  88 +}
  89 +
  90 +void SP_OnlineSidList :: add( SP_Sid_t sid )
  91 +{
  92 + sp_thread_mutex_lock( &mMutex );
  93 +
  94 + mList.add( sid );
  95 +
  96 + sp_thread_mutex_unlock( &mMutex );
  97 +}
  98 +
  99 +int SP_OnlineSidList :: getCount()
  100 +{
  101 + int count = 0;
  102 +
  103 + sp_thread_mutex_lock( &mMutex );
  104 +
  105 + count = mList.getCount();
  106 +
  107 + sp_thread_mutex_unlock( &mMutex );
  108 +
  109 + return count;
  110 +}
  111 +
  112 +//---------------------------------------------------------
  113 +
  114 +class SP_ChatHandler : public SP_Handler {
  115 +public:
  116 + SP_ChatHandler( SP_OnlineSidList * onlineSidList );
  117 + virtual ~SP_ChatHandler();
  118 +
  119 + virtual int start( SP_Request * request, SP_Response * response );
  120 +
  121 + // return -1 : terminate session, 0 : continue
  122 + virtual int handle( SP_Request * request, SP_Response * response );
  123 +
  124 + virtual void error( SP_Response * response );
  125 +
  126 + virtual void timeout( SP_Response * response );
  127 +
  128 + virtual void close();
  129 +
  130 +private:
  131 + SP_Sid_t mSid;
  132 +
  133 + SP_OnlineSidList * mOnlineSidList;
  134 +
  135 + static int mMsgSeq;
  136 +
  137 + void broadcast( SP_Response * response, const char * buffer, SP_Sid_t * ignoreSid = 0 );
  138 +};
  139 +
  140 +int SP_ChatHandler :: mMsgSeq = 0;
  141 +
  142 +SP_ChatHandler :: SP_ChatHandler( SP_OnlineSidList * onlineSidList )
  143 +{
  144 + memset( &mSid, 0, sizeof( mSid ) );
  145 +
  146 + mOnlineSidList = onlineSidList;
  147 +}
  148 +
  149 +SP_ChatHandler :: ~SP_ChatHandler()
  150 +{
  151 +}
  152 +
  153 +void SP_ChatHandler :: broadcast( SP_Response * response, const char * buffer, SP_Sid_t * ignoreSid )
  154 +{
  155 + if( mOnlineSidList->getCount() > 0 ) {
  156 + SP_Message * msg = new SP_Message();
  157 + mOnlineSidList->copy( msg->getToList(), ignoreSid );
  158 + msg->setCompletionKey( ++mMsgSeq );
  159 +
  160 + msg->getMsg()->append( buffer );
  161 + response->addMessage( msg );
  162 + }
  163 +}
  164 +
  165 +int SP_ChatHandler :: start( SP_Request * request, SP_Response * response )
  166 +{
  167 + request->setMsgDecoder( new SP_MultiLineMsgDecoder() );
  168 +
  169 + mSid = response->getFromSid();
  170 +
  171 + char buffer[ 128 ] = { 0 };
  172 + snprintf( buffer, sizeof( buffer ),
  173 + "Welcome %d to chat server, enter 'quit' to quit.\r\n", mSid.mKey );
  174 + response->getReply()->getMsg()->append( buffer );
  175 + response->getReply()->setCompletionKey( ++mMsgSeq );
  176 +
  177 + snprintf( buffer, sizeof( buffer ), "SYS : %d online\r\n", mSid.mKey);
  178 +
  179 + broadcast( response, buffer );
  180 +
  181 + mOnlineSidList->add( mSid );
  182 +
  183 + return 0;
  184 +}
  185 +
  186 +int SP_ChatHandler :: handle( SP_Request * request, SP_Response * response )
  187 +{
  188 + SP_MultiLineMsgDecoder * decoder = (SP_MultiLineMsgDecoder*)request->getMsgDecoder();
  189 + SP_CircleQueue * msgQueue = decoder->getQueue();
  190 +
  191 + char buffer[ 256 ] = { 0 };
  192 + int ret = 0;
  193 +
  194 + for( ; NULL != msgQueue->top(); ) {
  195 + char * line = (char*)msgQueue->pop();
  196 + if( 0 != strcasecmp( line, "quit" ) ) {
  197 + snprintf( buffer, sizeof( buffer ), "%d say: %s\r\n", mSid.mKey, line );
  198 + broadcast( response, buffer );
  199 + } else {
  200 + snprintf( buffer, sizeof( buffer ), "SYS : %d normal offline\r\n", mSid.mKey );
  201 + broadcast( response, buffer, &mSid );
  202 +
  203 + response->getReply()->getMsg()->append( "SYS : Byebye\r\n" );
  204 + response->getReply()->setCompletionKey( ++mMsgSeq );
  205 +
  206 + ret = -1;
  207 + }
  208 +
  209 + free( line );
  210 + }
  211 +
  212 + return ret;
  213 +}
  214 +
  215 +void SP_ChatHandler :: error( SP_Response * response )
  216 +{
  217 + char buffer[ 64 ] = { 0 };
  218 + snprintf( buffer, sizeof( buffer ), "SYS : %d error offline\r\n", mSid.mKey );
  219 +
  220 + broadcast( response, buffer, &mSid );
  221 +}
  222 +
  223 +void SP_ChatHandler :: timeout( SP_Response * response )
  224 +{
  225 + char buffer[ 64 ] = { 0 };
  226 + snprintf( buffer, sizeof( buffer ), "SYS : %d timeout offline\r\n", mSid.mKey );
  227 +
  228 + broadcast( response, buffer, &mSid );
  229 +}
  230 +
  231 +void SP_ChatHandler :: close()
  232 +{
  233 + mOnlineSidList->remove( mSid );
  234 +}
  235 +
  236 +//---------------------------------------------------------
  237 +
  238 +class SP_ChatCompletionHandler : public SP_CompletionHandler {
  239 +public:
  240 + SP_ChatCompletionHandler();
  241 + ~SP_ChatCompletionHandler();
  242 + virtual void completionMessage( SP_Message * msg );
  243 +};
  244 +
  245 +SP_ChatCompletionHandler :: SP_ChatCompletionHandler()
  246 +{
  247 +}
  248 +
  249 +SP_ChatCompletionHandler :: ~SP_ChatCompletionHandler()
  250 +{
  251 +}
  252 +
  253 +void SP_ChatCompletionHandler :: completionMessage( SP_Message * msg )
  254 +{
  255 +#if 0
  256 + printf( "message completed { completion key : %d }\n", msg->getCompletionKey() );
  257 +
  258 + printf( "\tsuccess {" );
  259 + for( int i = 0; i < msg->getSuccess()->getCount(); i++ ) {
  260 + printf( " %d", msg->getSuccess()->get( i ).mKey );
  261 + }
  262 + printf( "}\n" );
  263 +
  264 + printf( "\tfailure {" );
  265 + for( int i = 0; i < msg->getFailure()->getCount(); i++ ) {
  266 + printf( " %d", msg->getFailure()->get( i ).mKey );
  267 + }
  268 + printf( "}\n" );
  269 +#endif
  270 +
  271 + delete msg;
  272 +}
  273 +
  274 +//---------------------------------------------------------
  275 +
  276 +class SP_ChatHandlerFactory : public SP_HandlerFactory {
  277 +public:
  278 + SP_ChatHandlerFactory( SP_OnlineSidList * onlineSidList );
  279 + virtual ~SP_ChatHandlerFactory();
  280 +
  281 + virtual SP_Handler * create() const;
  282 +
  283 + virtual SP_CompletionHandler * createCompletionHandler() const;
  284 +
  285 +private:
  286 + SP_OnlineSidList * mOnlineSidList;
  287 +};
  288 +
  289 +SP_ChatHandlerFactory :: SP_ChatHandlerFactory( SP_OnlineSidList * onlineSidList )
  290 +{
  291 + mOnlineSidList = onlineSidList;
  292 +}
  293 +
  294 +SP_ChatHandlerFactory :: ~SP_ChatHandlerFactory()
  295 +{
  296 +}
  297 +
  298 +SP_Handler * SP_ChatHandlerFactory :: create() const
  299 +{
  300 + return new SP_ChatHandler( mOnlineSidList );
  301 +}
  302 +
  303 +SP_CompletionHandler * SP_ChatHandlerFactory :: createCompletionHandler() const
  304 +{
  305 + return new SP_ChatCompletionHandler();
  306 +}
  307 +
  308 +//---------------------------------------------------------
  309 +
  310 +int main( int argc, char * argv[] )
  311 +{
  312 + int port = 5555, maxThreads = 10;
  313 +
  314 + if( 0 != sp_initsock() ) assert( 0 );
  315 +
  316 + SP_OnlineSidList onlineSidList;
  317 +
  318 + SP_IocpServer server( "", port, new SP_ChatHandlerFactory( &onlineSidList ) );
  319 + server.setTimeout( 60 );
  320 + server.setMaxThreads( maxThreads );
  321 + server.setReqQueueSize( 100, "Sorry, server is busy now!\n" );
  322 +
  323 + server.runForever();
  324 +
  325 + sp_closelog();
  326 +
  327 + return 0;
  328 +}
  329 +
... ...
注册登录 后发表评论