正在显示
1 个修改的文件
包含
268 行增加
和
0 行删除
src/server/spserver/teststress.cpp
0 → 100644
1 | +/* | |
2 | + * Copyright 2007 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 | +#ifdef WIN32 | |
15 | +#include "spgetopt.h" | |
16 | +#endif | |
17 | + | |
18 | +#include "spporting.hpp" | |
19 | + | |
20 | +#include "event.h" | |
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 | +static int gConnWait = 0; | |
27 | +static int gSockWait = 0; | |
28 | + | |
29 | +static time_t gStartTime = 0; | |
30 | + | |
31 | +struct SP_TestClient { | |
32 | + int mFd; | |
33 | + struct event mReadEvent; | |
34 | + struct event mWriteEvent; | |
35 | + int mSendMsgs; | |
36 | + int mRecvMsgs; | |
37 | + char mBuffer[ 512 ]; | |
38 | +}; | |
39 | + | |
40 | +void showUsage( const char * program ) | |
41 | +{ | |
42 | + printf( "\nStress Test Tools for spserver example -- testecho/testchat\n\n" ); | |
43 | + printf( "Usage: %s [-h <host>] [-p <port>] [-c <clients>] [-m <messages>]\n" | |
44 | + "\t\t\t[-w <connect wait>] [-s <socket wait>]\n\n", program ); | |
45 | + printf( "\t-h default is %s\n", gHost ); | |
46 | + printf( "\t-p default is %d\n", gPort ); | |
47 | + printf( "\t-c how many clients, default is %d\n", gClients ); | |
48 | + printf( "\t-m messages per client, default is %d\n", gMsgs ); | |
49 | + printf( "\t-w how many milliseconds to wait between creating every 100 connections, default is %d\n", gConnWait ); | |
50 | + printf( "\t-s how many milliseconds to wait between every event loop, default is %d\n", gSockWait ); | |
51 | + printf( "\n" ); | |
52 | +} | |
53 | + | |
54 | +void close_read( SP_TestClient * client ) | |
55 | +{ | |
56 | + //fprintf( stderr, "#%d close read\n", client->mFd ); | |
57 | + event_del( &client->mReadEvent ); | |
58 | + gClients--; | |
59 | +} | |
60 | + | |
61 | +void close_write( SP_TestClient * client ) | |
62 | +{ | |
63 | + //fprintf( stderr, "#%d close write\n", client->mFd ); | |
64 | + event_del( &client->mWriteEvent ); | |
65 | +} | |
66 | + | |
67 | +void close_client( SP_TestClient * client ) | |
68 | +{ | |
69 | + close_write( client ); | |
70 | + close_read( client ); | |
71 | +} | |
72 | + | |
73 | +void on_read( int fd, short events, void *arg ) | |
74 | +{ | |
75 | + SP_TestClient * client = ( SP_TestClient * ) arg; | |
76 | + | |
77 | + if( EV_READ & events ) { | |
78 | + int len = recv( fd, client->mBuffer, sizeof( client->mBuffer ), 0 ); | |
79 | + if( len <= 0 ) { | |
80 | + if( len < 0 && EAGAIN != errno ) { | |
81 | + fprintf( stderr, "#%d on_read error, count %d, errno %d, %s\n", | |
82 | + fd, client->mRecvMsgs, errno, strerror( errno ) ); | |
83 | + } | |
84 | + close_client( client ); | |
85 | + } else { | |
86 | + for( int i = 0; i < len; i++ ) { | |
87 | + //if( 10 == fd ) printf( "%c", client->mBuffer[i] ); | |
88 | + if( '\n' == client->mBuffer[i] ) client->mRecvMsgs++; | |
89 | + } | |
90 | + } | |
91 | + } else { | |
92 | + fprintf( stderr, "#%d on_read timeout\n", fd ); | |
93 | + close_client( client ); | |
94 | + } | |
95 | +} | |
96 | + | |
97 | +void on_write( int fd, short events, void *arg ) | |
98 | +{ | |
99 | + SP_TestClient * client = ( SP_TestClient * ) arg; | |
100 | + | |
101 | + if( EV_WRITE & events ) { | |
102 | + client->mSendMsgs++; | |
103 | + | |
104 | + if( client->mSendMsgs >= gMsgs ) { | |
105 | + snprintf( client->mBuffer, sizeof( client->mBuffer ), "quit\n" ); | |
106 | + } else { | |
107 | + snprintf( client->mBuffer, sizeof( client->mBuffer ), | |
108 | + "mail #%d, It's good to see how people hire; " | |
109 | + "that tells us how to market ourselves to them.\n", client->mSendMsgs ); | |
110 | + } | |
111 | + | |
112 | + int len = send( fd, client->mBuffer, strlen( client->mBuffer ), 0 ); | |
113 | + | |
114 | + if( len <= 0 && EAGAIN != errno ) { | |
115 | + fprintf( stderr, "#%d on_write error, errno %d, %s\n", fd, errno, strerror( errno ) ); | |
116 | + close_client( client ); | |
117 | + } else { | |
118 | + if( client->mSendMsgs >= gMsgs ) close_write( client ); | |
119 | + } | |
120 | + } else { | |
121 | + fprintf( stderr, "#%d on_write timeout\n", fd ); | |
122 | + close_client( client ); | |
123 | + } | |
124 | +} | |
125 | + | |
126 | +void parse_arg( int argc, char * argv[] ) | |
127 | +{ | |
128 | + extern char *optarg ; | |
129 | + int c ; | |
130 | + | |
131 | + while( ( c = getopt ( argc, argv, "h:p:c:m:w:s:v" )) != EOF ) { | |
132 | + switch ( c ) { | |
133 | + case 'h' : | |
134 | + gHost = optarg; | |
135 | + break; | |
136 | + case 'p': | |
137 | + gPort = atoi( optarg ); | |
138 | + break; | |
139 | + case 'c' : | |
140 | + gClients = atoi ( optarg ); | |
141 | + break; | |
142 | + case 'm' : | |
143 | + gMsgs = atoi( optarg ); | |
144 | + break; | |
145 | + case 'w': | |
146 | + gConnWait = atoi( optarg ); | |
147 | + break; | |
148 | + case 's': | |
149 | + gSockWait = atoi( optarg ); | |
150 | + break; | |
151 | + case 'v' : | |
152 | + case '?' : | |
153 | + showUsage( argv[0] ); | |
154 | + exit( 0 ); | |
155 | + } | |
156 | + } | |
157 | +} | |
158 | + | |
159 | +int main( int argc, char * argv[] ) | |
160 | +{ | |
161 | + parse_arg( argc, argv ); | |
162 | + | |
163 | +#ifdef SIGPIPE | |
164 | + signal( SIGPIPE, SIG_IGN ); | |
165 | +#endif | |
166 | + | |
167 | + sp_initsock(); | |
168 | + | |
169 | + event_init(); | |
170 | + | |
171 | + SP_TestClient * clientList = (SP_TestClient*)calloc( gClients, sizeof( SP_TestClient ) ); | |
172 | + | |
173 | + struct sockaddr_in sin; | |
174 | + memset( &sin, 0, sizeof(sin) ); | |
175 | + sin.sin_family = AF_INET; | |
176 | + sin.sin_addr.s_addr = inet_addr( gHost ); | |
177 | + sin.sin_port = htons( gPort ); | |
178 | + | |
179 | + int totalClients = gClients, i = 0; | |
180 | + | |
181 | + printf( "Create %d connections to server, it will take some minutes to complete.\n", gClients ); | |
182 | + for( i = 0; i < gClients; i++ ) { | |
183 | + SP_TestClient * client = clientList + i; | |
184 | + | |
185 | + client->mFd = socket( AF_INET, SOCK_STREAM, 0 ); | |
186 | + if( client->mFd < 0 ) { | |
187 | + fprintf(stderr, "#%d, socket failed, errno %d, %s\n", i, errno, strerror( errno ) ); | |
188 | +#ifdef WIN32 | |
189 | + spwin32_pause_console(); | |
190 | +#endif | |
191 | + return -1; | |
192 | + } | |
193 | + | |
194 | + if( connect( client->mFd, (struct sockaddr *)&sin, sizeof(sin) ) != 0) { | |
195 | + fprintf(stderr, "#%d, connect failed, errno %d, %s\n", i, errno, strerror( errno ) ); | |
196 | +#ifdef WIN32 | |
197 | + spwin32_pause_console(); | |
198 | +#endif | |
199 | + return -1; | |
200 | + } | |
201 | + | |
202 | + event_set( &client->mWriteEvent, client->mFd, EV_WRITE | EV_PERSIST, on_write, client ); | |
203 | + event_add( &client->mWriteEvent, NULL ); | |
204 | + | |
205 | + event_set( &client->mReadEvent, client->mFd, EV_READ | EV_PERSIST, on_read, client ); | |
206 | + event_add( &client->mReadEvent, NULL ); | |
207 | + | |
208 | + if( 0 == ( i % 10 ) ) write( fileno( stdout ), ".", 1 ); | |
209 | + | |
210 | + if( gConnWait > 0 && ( i > 0 ) && ( 0 == ( i % 100 ) ) ) usleep( gConnWait * 1000 ); | |
211 | + } | |
212 | + | |
213 | + time( &gStartTime ); | |
214 | + | |
215 | + struct timeval startTime, stopTime; | |
216 | + | |
217 | + sp_gettimeofday( &startTime, NULL ); | |
218 | + | |
219 | + time_t lastInfoTime = time( NULL ); | |
220 | + | |
221 | + // start event loop until all clients are exit | |
222 | + while( gClients > 0 ) { | |
223 | + event_loop( EVLOOP_ONCE ); | |
224 | + | |
225 | + if( time( NULL ) - lastInfoTime > 5 ) { | |
226 | + time( &lastInfoTime ); | |
227 | + printf( "waiting for %d client(s) to exit\n", gClients ); | |
228 | + } | |
229 | + | |
230 | + if( gSockWait > 0 ) usleep( gSockWait * 1000 ); | |
231 | + } | |
232 | + | |
233 | + sp_gettimeofday( &stopTime, NULL ); | |
234 | + | |
235 | + double totalTime = (double) ( 1000000 * ( stopTime.tv_sec - startTime.tv_sec ) | |
236 | + + ( stopTime.tv_usec - startTime.tv_usec ) ) / 1000000; | |
237 | + | |
238 | + // show result | |
239 | + printf( "\n\nTest result :\n" ); | |
240 | + printf( "Host %s, Port %d, ConnWait: %d, SockWait: %d\n", gHost, gPort, gConnWait, gSockWait ); | |
241 | + printf( "Clients : %d, Messages Per Client : %d\n", totalClients, gMsgs ); | |
242 | + printf( "ExecTimes: %.6f seconds\n\n", totalTime ); | |
243 | + | |
244 | + printf( "client\tSend\tRecv\n" ); | |
245 | + int totalSend = 0, totalRecv = 0; | |
246 | + for( i = 0; i < totalClients; i++ ) { | |
247 | + SP_TestClient * client = clientList + i; | |
248 | + | |
249 | + //printf( "client#%d : %d\t%d\n", i, client->mSendMsgs, client->mRecvMsgs ); | |
250 | + | |
251 | + totalSend += client->mSendMsgs; | |
252 | + totalRecv += client->mRecvMsgs; | |
253 | + | |
254 | + sp_close( client->mFd ); | |
255 | + } | |
256 | + | |
257 | + printf( "total : %d\t%d\n", totalSend, totalRecv ); | |
258 | + printf( "average : %.0f/s\t%.0f/s\n", totalSend / totalTime, totalRecv / totalTime ); | |
259 | + | |
260 | + free( clientList ); | |
261 | + | |
262 | +#ifdef WIN32 | |
263 | + spwin32_pause_console(); | |
264 | +#endif | |
265 | + | |
266 | + return 0; | |
267 | +} | |
268 | + | ... | ... |
请
注册
或
登录
后发表评论