提交 93633716bceec8207f0471c873c006bc82c1bed2

作者 LJH 李佳桓
1 个父辈 c512ef10

add

  1 +/*
  2 + * Copyright 2008 Stephen Liu
  3 + * For license terms, see the file COPYING along with this library.
  4 + */
  5 +
  6 +#include <signal.h>
  7 +#include <stdio.h>
  8 +#include <sys/types.h>
  9 +#include <stdlib.h>
  10 +#include <errno.h>
  11 +#include <time.h>
  12 +#include <string.h>
  13 +
  14 +#include "spgetopt.h"
  15 +
  16 +#include "spwin32port.hpp"
  17 +
  18 +#pragma comment(lib,"ws2_32")
  19 +#pragma comment(lib,"mswsock")
  20 +#pragma comment(lib,"advapi32")
  21 +
  22 +static const char * gHost = "127.0.0.1";
  23 +static int gPort = 3333;
  24 +static int gMsgs = 10;
  25 +static int gClients = 10;
  26 +
  27 +struct SP_TestStat {
  28 + int mRecvFail;
  29 + int mWSARecvFail;
  30 +
  31 + int mSendFail;
  32 + int mWSASendFail;
  33 +
  34 + int mGQCSFail;
  35 +};
  36 +
  37 +static struct SP_TestStat gStat;
  38 +static time_t gStartTime = 0;
  39 +
  40 +struct SP_TestEvent {
  41 + enum { eEventRecv, eEventSend };
  42 +
  43 + OVERLAPPED mOverlapped;
  44 + WSABUF mWsaBuf;
  45 + int mType;
  46 +};
  47 +
  48 +struct SP_TestClient {
  49 + SOCKET mFd;
  50 +
  51 + SP_TestEvent mRecvEvent;
  52 + SP_TestEvent mSendEvent;
  53 +
  54 + int mSendMsgs;
  55 + int mRecvMsgs;
  56 + int mIsStop;
  57 +};
  58 +
  59 +void showUsage( const char * program )
  60 +{
  61 + printf( "Stress Test Tools for spserver example\n" );
  62 + printf( "Usage: %s [-h <host>] [-p <port>] [-c <clients>] [-m <messages>]\n", program );
  63 + printf( "\t-h default is %s\n", gHost );
  64 + printf( "\t-p default is %d\n", gPort );
  65 + printf( "\t-c how many clients, default is %d\n", gClients );
  66 + printf( "\t-m messages per client, default is %d\n", gMsgs );
  67 + printf( "\n" );
  68 +}
  69 +
  70 +void close_client( SP_TestClient * client )
  71 +{
  72 + if( 0 == client->mIsStop ) {
  73 + client->mIsStop = 1;
  74 + gClients--;
  75 + }
  76 +}
  77 +
  78 +void on_read( SP_TestClient * client, SP_TestEvent * event )
  79 +{
  80 + char buffer[ 4096 ] = { 0 };
  81 + int bytesTransferred = recv( (int)client->mFd, buffer, sizeof( buffer ), 0 );
  82 +
  83 + if( bytesTransferred <= 0 ) {
  84 + if( bytesTransferred < 0 ) {
  85 + printf( "recv fail, errno %d\n", WSAGetLastError() );
  86 + gStat.mRecvFail++;
  87 + }
  88 + close_client( client );
  89 + return;
  90 + }
  91 +
  92 + for( int i = 0; i < bytesTransferred; i++ ) {
  93 + if( '\n' == buffer[i] ) client->mRecvMsgs++;
  94 + }
  95 +
  96 + memset( &( event->mOverlapped ), 0, sizeof( OVERLAPPED ) );
  97 + event->mType = SP_TestEvent::eEventRecv;
  98 + event->mWsaBuf.buf = NULL;
  99 + event->mWsaBuf.len = 0;
  100 +
  101 + DWORD recvBytes = 0, flags = 0;
  102 + if( SOCKET_ERROR == WSARecv( (SOCKET)client->mFd, &( event->mWsaBuf ), 1,
  103 + &recvBytes, &flags, &( event->mOverlapped ), NULL ) ) {
  104 + if( ERROR_IO_PENDING != WSAGetLastError() ) {
  105 + gStat.mWSARecvFail++;
  106 + printf( "WSARecv fail, errno %d\n", WSAGetLastError() );
  107 + close_client( client );
  108 + }
  109 + }
  110 +}
  111 +
  112 +void on_write( SP_TestClient * client, SP_TestEvent * event )
  113 +{
  114 + if( client->mSendMsgs < gMsgs ) {
  115 + client->mSendMsgs++;
  116 +
  117 + char buffer[ 4096 ] = { 0 };
  118 + if( client->mSendMsgs >= gMsgs ) {
  119 + snprintf( buffer, sizeof( buffer ), "quit\n" );
  120 + } else {
  121 + snprintf( buffer, sizeof( buffer ),
  122 + "mail #%d, It's good to see how people hire; "
  123 + "that tells us how to market ourselves to them.\n", client->mSendMsgs );
  124 + }
  125 +
  126 + int bytesTransferred = send( (SOCKET)client->mFd, buffer, strlen( buffer ), 0 );
  127 + if( bytesTransferred <= 0 ) {
  128 + if( bytesTransferred < 0 ) {
  129 + printf( "send fail, errno %d\n", WSAGetLastError() );
  130 + gStat.mSendFail++;
  131 + }
  132 + close_client( client );
  133 + return;
  134 + }
  135 +
  136 + DWORD sendBytes = 0;
  137 +
  138 + event->mType = SP_TestEvent::eEventSend;
  139 + memset( &( event->mOverlapped ), 0, sizeof( OVERLAPPED ) );
  140 + event->mWsaBuf.buf = NULL;
  141 + event->mWsaBuf.len = 0;
  142 +
  143 + if( SOCKET_ERROR == WSASend( (SOCKET)client->mFd, &( event->mWsaBuf ), 1,
  144 + &sendBytes, 0, &( event->mOverlapped ), NULL ) ) {
  145 + if( ERROR_IO_PENDING != WSAGetLastError() ) {
  146 + gStat.mWSASendFail++;
  147 + printf( "WSASend fail, errno %d\n", WSAGetLastError() );
  148 + close_client( client );
  149 + }
  150 + }
  151 + } else {
  152 + // do nothing
  153 + }
  154 +}
  155 +
  156 +void eventLoop( HANDLE hIocp )
  157 +{
  158 + DWORD bytesTransferred = 0;
  159 + SP_TestClient * client = NULL;
  160 + SP_TestEvent * event = NULL;
  161 +
  162 + BOOL isSuccess = GetQueuedCompletionStatus( hIocp, &bytesTransferred,
  163 + (DWORD*)&client, (OVERLAPPED**)&event, 100 );
  164 + DWORD lastError = WSAGetLastError();
  165 +
  166 + if( ! isSuccess ) {
  167 + if( NULL != client ) {
  168 + gStat.mGQCSFail++;
  169 + close_client( client );
  170 + }
  171 + return;
  172 + }
  173 +
  174 + if( SP_TestEvent::eEventRecv == event->mType ) {
  175 + on_read( client, event );
  176 + return;
  177 + }
  178 +
  179 + if( SP_TestEvent::eEventSend == event->mType ) {
  180 + on_write( client, event );
  181 + return;
  182 + }
  183 +}
  184 +
  185 +int main( int argc, char * argv[] )
  186 +{
  187 + extern char *optarg ;
  188 + int c ;
  189 +
  190 + while( ( c = getopt ( argc, argv, "h:p:c:m:v" )) != EOF ) {
  191 + switch ( c ) {
  192 + case 'h' :
  193 + gHost = optarg;
  194 + break;
  195 + case 'p':
  196 + gPort = atoi( optarg );
  197 + break;
  198 + case 'c' :
  199 + gClients = atoi ( optarg );
  200 + break;
  201 + case 'm' :
  202 + gMsgs = atoi( optarg );
  203 + break;
  204 + case 'v' :
  205 + case '?' :
  206 + showUsage( argv[0] );
  207 + exit( 0 );
  208 + }
  209 + }
  210 +
  211 +#ifdef SIGPIPE
  212 + signal( SIGPIPE, SIG_IGN );
  213 +#endif
  214 +
  215 + WSADATA wsaData;
  216 +
  217 + int err = WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
  218 + if ( err != 0 ) {
  219 + printf( "Couldn't find a useable winsock.dll.\n" );
  220 + return -1;
  221 + }
  222 +
  223 + HANDLE hIocp = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );
  224 + if( NULL == hIocp ) {
  225 + printf( "CreateIoCompletionPort failed, errno %d\n", WSAGetLastError() );
  226 + return -1;
  227 + }
  228 +
  229 + SP_TestClient * clientList = (SP_TestClient*)calloc( gClients, sizeof( SP_TestClient ) );
  230 +
  231 + struct sockaddr_in sin;
  232 + memset( &sin, 0, sizeof(sin) );
  233 + sin.sin_family = AF_INET;
  234 + sin.sin_addr.s_addr = inet_addr( gHost );
  235 + sin.sin_port = htons( gPort );
  236 +
  237 + int totalClients = gClients, i = 0;
  238 +
  239 + printf( "Create %d connections to server, it will take some minutes to complete.\n", gClients );
  240 + for( i = 0; i < gClients; i++ ) {
  241 + SP_TestClient * client = clientList + i;
  242 + memset( client, 0, sizeof( SP_TestClient ) );
  243 +
  244 + client->mFd = socket( AF_INET, SOCK_STREAM, 0 );
  245 + if( client->mFd < 0 ) {
  246 + printf( "socket failed, errno %d, %s\n", errno, strerror( errno ) );
  247 + spwin32_pause_console();
  248 + return -1;
  249 + }
  250 +
  251 + if( connect( client->mFd, (struct sockaddr *)&sin, sizeof(sin) ) != 0) {
  252 + printf( "connect failed, errno %d, %s\n", errno, strerror( errno ) );
  253 + spwin32_pause_console();
  254 + return -1;
  255 + }
  256 +
  257 + if( NULL == CreateIoCompletionPort( (HANDLE)client->mFd, hIocp, (DWORD)client, 0 ) ) {
  258 + printf( "CreateIoCompletionPort failed, errno %d\n", WSAGetLastError() );
  259 + return -1;
  260 + }
  261 +
  262 + if( 0 == ( i % 10 ) ) printf( "." );
  263 + }
  264 +
  265 + for( i = 0; i < gClients; i++ ) {
  266 + SP_TestClient * client = clientList + i;
  267 + on_read( client, &( client->mRecvEvent ) );
  268 + on_write( client, &( client->mSendEvent ) );
  269 + }
  270 +
  271 + printf( "\n" );
  272 +
  273 + time( &gStartTime );
  274 +
  275 + struct timeval startTime, stopTime;
  276 +
  277 + sp_gettimeofday( &startTime, NULL );
  278 +
  279 + time_t lastInfoTime = time( NULL );
  280 +
  281 + // start event loop until all clients are exit
  282 + while( gClients > 0 ) {
  283 + eventLoop( hIocp );
  284 +
  285 + if( time( NULL ) - lastInfoTime > 5 ) {
  286 + time( &lastInfoTime );
  287 + printf( "waiting for %d client(s) to exit\n", gClients );
  288 + }
  289 + }
  290 +
  291 + sp_gettimeofday( &stopTime, NULL );
  292 +
  293 + double totalTime = (double) ( 1000000 * ( stopTime.tv_sec - startTime.tv_sec )
  294 + + ( stopTime.tv_usec - startTime.tv_usec ) ) / 1000000;
  295 +
  296 + // show result
  297 + printf( "\n\nTest result :\n" );
  298 + printf( "Clients : %d, Messages Per Client : %d\n", totalClients, gMsgs );
  299 + printf( "Failure : send %d, WSASend %d, recv %d, WSARecv %d, GQCS %d\n",
  300 + gStat.mSendFail, gStat.mWSASendFail, gStat.mRecvFail,
  301 + gStat.mWSARecvFail, gStat.mGQCSFail );
  302 + printf( "ExecTimes : %.6f seconds\n\n", totalTime );
  303 +
  304 + printf( "client\tSend\tRecv\n" );
  305 + int totalSend = 0, totalRecv = 0;
  306 + for( i = 0; i < totalClients; i++ ) {
  307 + SP_TestClient * client = clientList + i;
  308 +
  309 + //printf( "client#%d : %d\t%d\n", i, client->mSendMsgs, client->mRecvMsgs );
  310 +
  311 + totalSend += client->mSendMsgs;
  312 + totalRecv += client->mRecvMsgs;
  313 +
  314 + if( INVALID_HANDLE_VALUE != (HANDLE)client->mFd ) {
  315 + closesocket( client->mFd );
  316 + }
  317 + }
  318 +
  319 + printf( "total : %d\t%d\n", totalSend, totalRecv );
  320 + printf( "average : %.0f/s\t%.0f/s\n", totalSend / totalTime, totalRecv / totalTime );
  321 +
  322 + free( clientList );
  323 +
  324 + CloseHandle( hIocp );
  325 +
  326 + spwin32_pause_console();
  327 +
  328 + return 0;
  329 +}
  330 +
... ...
注册登录 后发表评论