/* * Copyright 2008 Stephen Liu * For license terms, see the file COPYING along with this library. */ #include #include #include #include #define _CRTDBG_MAP_ALLOC #include #include #include "spwin32iocp.hpp" #include "spiocpserver.hpp" #include "spiocplfserver.hpp" #include "spsession.hpp" #include "spbuffer.hpp" #include "spmsgdecoder.hpp" #include "sprequest.hpp" #include "sphandler.hpp" #include "sputils.hpp" #include "spgetopt.h" #pragma comment(lib,"ws2_32") #pragma comment(lib,"mswsock") #pragma comment(lib,"advapi32") class SP_EchoHandler : public SP_Handler { public: SP_EchoHandler(){} virtual ~SP_EchoHandler(){} // return -1 : terminate session, 0 : continue virtual int start( SP_Request * request, SP_Response * response ) { request->setMsgDecoder( new SP_MultiLineMsgDecoder() ); response->getReply()->getMsg()->append( "Welcome to line echo server, enter 'quit' to quit.\r\n" ); return 0; } // return -1 : terminate session, 0 : continue virtual int handle( SP_Request * request, SP_Response * response ) { SP_MultiLineMsgDecoder * decoder = (SP_MultiLineMsgDecoder*)request->getMsgDecoder(); SP_CircleQueue * queue = decoder->getQueue(); int ret = 0; for( ; NULL != queue->top(); ) { char * line = (char*)queue->pop(); if( 0 != strcasecmp( line, "quit" ) ) { response->getReply()->getMsg()->append( line ); response->getReply()->getMsg()->append( "\r\n" ); } else { response->getReply()->getMsg()->append( "Byebye\r\n" ); ret = -1; } free( line ); } return ret; } virtual void error( SP_Response * response ) {} virtual void timeout( SP_Response * response ) {} virtual void close() {} }; class SP_EchoHandlerFactory : public SP_HandlerFactory { public: SP_EchoHandlerFactory() {} virtual ~SP_EchoHandlerFactory() {} virtual SP_Handler * create() const { return new SP_EchoHandler(); } }; void IncreaseConnections() { SetProcessWorkingSetSize( GetCurrentProcess(), 10 * 1024 * 1024, 400 * 1024 * 1024 ); DWORD minSize = 0, maxSize = 0; GetProcessWorkingSetSize( GetCurrentProcess(), &minSize, &maxSize ); printf( "WorkingSetSize min %d(%d), max %d(%d)\n", minSize, minSize / 4096, maxSize, maxSize / 4096 ); HKEY hKey; /* http://support.microsoft.com/default.aspx?scid=kb;EN-US;314053 */ printf("Writing to registry... \n"); if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Winsock", 0, KEY_WRITE, &hKey ) != ERROR_SUCCESS ) { printf( "RegOpenKeyEx fail, errno %d\n", GetLastError() ); } else { DWORD dwCon = 0xfffffe; if( RegSetValueEx( hKey, "TcpNumConnections", 0, REG_DWORD, (const BYTE *) &dwCon, sizeof(dwCon) ) != ERROR_SUCCESS ) { printf( "RegSetValueEx fail, errno %d\n", GetLastError() ); } RegCloseKey( hKey ); } } int main( int argc, char * argv[] ) { int port = 3333, maxThreads = 4, maxConnections = 20000; int timeout = 120, reqQueueSize = 10000; const char * serverType = "lf"; extern char *optarg ; int c ; while( ( c = getopt ( argc, argv, "p:t:o:c:q:s:v" )) != EOF ) { switch ( c ) { case 'p' : port = atoi( optarg ); break; case 't': maxThreads = atoi( optarg ); break; case 'c': maxConnections = atoi( optarg ); break; case 'o': timeout = atoi( optarg ); break; case 'q': reqQueueSize = atoi( optarg ); break; case 's': serverType = optarg; break; case '?' : case 'v' : printf( "Usage: %s [-p ] [-t ] [-c ] " "[-o ] [-q ] [-s ]\n", argv[0] ); exit( 0 ); } } if( 0 != sp_initsock() ) assert( 0 ); //Warning: This modifies your operating system. Use it at your own risk. //IncreaseConnections(); sp_syslog( LOG_DEBUG, "server type %s", serverType ); if( 0 == strcasecmp( serverType, "hahs" ) ) { SP_IocpServer server( "", port, new SP_EchoHandlerFactory() ); server.setTimeout( timeout ); server.setMaxThreads( maxThreads ); server.setReqQueueSize( reqQueueSize, "Byebye\r\n" ); server.setMaxConnections( maxConnections ); server.runForever(); } else { SP_IocpLFServer server( "", port, new SP_EchoHandlerFactory() ); server.setTimeout( timeout ); server.setMaxThreads( maxThreads ); server.setReqQueueSize( reqQueueSize, "Byebye\r\n" ); server.setMaxConnections( maxConnections ); server.runForever(); } return 0; }