singrdk/base/Windows/gulp/gulp.c

417 lines
12 KiB
C
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
#include "winlean.h"
#include "winsock2.h"
#include <stdlib.h>
#include <stdio.h>
2008-11-17 18:29:00 -05:00
#define DEF_PACKET_SIZE 32
#define MAX_PACKET 1024
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
#define xmalloc(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (s))
#define xfree(p) HeapFree (GetProcessHeap(), 0, (p))
2008-03-05 09:52:00 -05:00
_declspec (thread) void * MC_MyCS_StopEvent;
typedef struct args {
2008-11-17 18:29:00 -05:00
LPTSTR host;
int port;
} thread_args_t, *pthread_args_t;
static HANDLE endThreadEvent;
static HANDLE threadCountMutex;
static int doneThreads;
static int numThreads;
static int iterationCount;
static int g_totalBytesRead;
//
//
// MC_GetLastErrorText
//
// PURPOSE: copies error message text to string
//
// PARAMETERS:
// lpszBuf - destination buffer
// dwSize - size of buffer
//
// RETURN VALUE:
// destination buffer
//
2008-03-05 09:52:00 -05:00
LPSTR MC_GetLastErrorText(LPSTR lpszBuf, DWORD dwSize, DWORD errnum)
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;
dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
errnum,
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL );
if ( !dwRet)
2008-11-17 18:29:00 -05:00
sprintf(lpszBuf, "error number %d", errnum); // no message so use errnum
2008-03-05 09:52:00 -05:00
else
{
2008-11-17 18:29:00 -05:00
lpszTemp[lstrlen(lpszTemp)-2] = '\0'; // remove cr and newline characters
2008-03-05 09:52:00 -05:00
//sprintf(lpszBuf, "%s (%d)", lpszTemp, errnum);
sprintf(lpszBuf, " error %d\n", errnum);
}
if (lpszTemp)
LocalFree((HLOCAL) lpszTemp );
return lpszBuf;
}
static void MC_ErrMsg(LPSTR buf, DWORD bufsize, LPCSTR msg)
{
DWORD tmp;
tmp = strlen(strcpy(buf, msg));
MC_GetLastErrorText(buf + tmp, bufsize - tmp, WSAGetLastError());
}
2008-11-17 18:29:00 -05:00
//
// FUNCTION: MC_Recv
//
// PURPOSE: A replacement for the Winsock recv() routine. This version uses
// overlapped I/O to look for data on a socket and also watch
// for the Stop event.
//
// PARAMETERS:
// sock - read from this socket.
// buffer - place incoming data into this buffer.
// nbytes - the amount of storage in the buffer.
//
// RETURN VALUE:
// -1 - error.
// 0 - the socket connection has been closed.
// >0 - the number of bytes read.
//
int
2008-03-05 09:52:00 -05:00
MC_Recv(SOCKET sock, char *buffer, int nbytes)
{
DWORD bytesreceived;
DWORD flags = 0;
WSAOVERLAPPED ov;
WSABUF wsabuffer[1];
HANDLE ourevents[2];
ov.hEvent = NULL;
ov.Offset = ov.OffsetHigh = 0;
wsabuffer[0].buf = buffer;
wsabuffer[0].len = nbytes;
while(1)
{
if (WSARecv(sock, wsabuffer, 1, &bytesreceived, &flags, &ov, NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError())
{
2008-11-17 18:29:00 -05:00
case WSAEWOULDBLOCK: continue; // try again
2008-03-05 09:52:00 -05:00
case WSAENETRESET:
case WSAECONNRESET:
2008-11-17 18:29:00 -05:00
case WSAEDISCON: return 0; // connection closed
2008-03-05 09:52:00 -05:00
//case WSA_IO_PENDING: break; /* okay */
2008-11-17 18:29:00 -05:00
default: return -1; // unexpected error
2008-03-05 09:52:00 -05:00
}
ourevents[0] = (HANDLE) sock;
ourevents[1] = MC_MyCS_StopEvent;
if (WaitForMultipleObjects(2, ourevents, FALSE, 10000) != WAIT_OBJECT_0)
{
printf("MC_Recv(): Stop event or WaitForMultipleObjects() error\n");
2008-11-17 18:29:00 -05:00
return -1; // Stop event or error
2008-03-05 09:52:00 -05:00
}
else if (!WSAGetOverlappedResult(sock, &ov, &bytesreceived, FALSE, &flags))
2008-11-17 18:29:00 -05:00
return -1; // error
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
return bytesreceived; // if we got here its due to a successful read
2008-03-05 09:52:00 -05:00
}
}
static DWORD Gulp(SOCKET sockfd )
{
2008-11-17 18:29:00 -05:00
int totalBytes;
int numPackets;
int bytesRead;
char buffer[4096];
totalBytes = 0;
numPackets = 0;
do {
bytesRead = MC_Recv(sockfd, buffer, 4096);
if (bytesRead > 0 ) {
numPackets++;
totalBytes += bytesRead;
}
} while (bytesRead > 0) ;
//printf(" Read %d bytes in %d receives\n", totalBytes, numPackets);
2008-03-05 09:52:00 -05:00
return totalBytes;
}
2008-11-17 18:29:00 -05:00
static DWORD WINAPI
2008-03-05 09:52:00 -05:00
MC_DoFetchUrl(LPVOID lpParam)
{
struct hostent *hostelement;
struct sockaddr_in sock_addr;
2008-11-17 18:29:00 -05:00
DWORD tmp;
int server_status = 0;
int ret_count = 0;
SOCKET sockfd;
pthread_args_t args;
char retmsg[1024];
int size_retmsg;
int i;
struct linger lo;
int bytesRead;
args = (pthread_args_t) lpParam;
size_retmsg = 1024;
bytesRead = 0;
for (i=0; i < iterationCount; i++) {
memset((void *) &sock_addr, '\0', sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons((short) (args->port > 0 ? args->port : 80));
if ((sockfd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET) {
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to create socket: ");
printf(retmsg);
//break;
}
if ((hostelement = gethostbyname(args->host)) == NULL) {
tmp = sprintf(retmsg, "Unable to resolve host name '%s':", args->host);
MC_GetLastErrorText(retmsg + tmp, size_retmsg - tmp, WSAGetLastError());
printf(retmsg);
break;
}
memcpy(&sock_addr.sin_addr, hostelement->h_addr, hostelement->h_length);
tmp = connect(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr));
if (tmp == SOCKET_ERROR) {
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to connect to web server: ");
printf(retmsg);
//break;
}
2008-03-05 09:52:00 -05:00
lo.l_onoff = 1;
lo.l_linger = 0;
2008-11-17 18:29:00 -05:00
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
(char *) &lo, sizeof(lo)) < 0) {
printf("HTDoConnect: Can't set sockopt SO_LINGER (%d)\n", errno);
break;
}
bytesRead += Gulp(sockfd);
shutdown(sockfd, SD_BOTH);
closesocket(sockfd);
}
WaitForSingleObject(threadCountMutex,INFINITE);
g_totalBytesRead += bytesRead;
doneThreads++;
printf("Thread ending..count=%d\n",doneThreads);
SetEvent(endThreadEvent);
ReleaseMutex(threadCountMutex);
2008-03-05 09:52:00 -05:00
return 1;
}
2008-11-17 18:29:00 -05:00
// print an error message and exit the program
2008-03-05 09:52:00 -05:00
void die (char *format,...) {
va_list args;
char buffer[2048], *ptr=buffer;
va_start(args,format);
ptr += vsprintf (ptr, format, args);
va_end (args);
*(ptr++) = '\n';
*(ptr++) = '\0';
printf( buffer);
exit(1);
}
int InitChildLayer(void) {
WORD wVersionRequested;
WSADATA wsaData;
int err;
int major, minor;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
2008-11-17 18:29:00 -05:00
// Tell the user that we couldn't find a useable
// WinSock DLL.
die ("Couldn't find a WinSock DLL!\n");
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
// Confirm that the WinSock DLL supports 2.0.
// Note that if the DLL supports versions greater
// than 2.0 in addition to 2.0, it will still return
// 2.0 in wVersion since that is the version we
// requested.
2008-03-05 09:52:00 -05:00
major = LOBYTE( wsaData.wVersion );
minor = LOBYTE( wsaData.wVersion );
if ( major < 1 || ( major == 1 && minor < 1 ) ) {
2008-11-17 18:29:00 -05:00
// Tell the user that we couldn't find a useable
// WinSock DLL.
WSACleanup( );
die ("Require at least WinSock 1.1, your version is %d.%d!\n",
major, minor);
2008-03-05 09:52:00 -05:00
}
return 0;
}
void Usage()
{
printf(
"Usage:\n"
" gulp [options] \n"
"Options:\n"
2008-11-17 18:29:00 -05:00
" /p:N -- Port to connect to (default=5000)\n"
" /a:nnn.nnn.nnn -- address to connect to\n"
" /i:N -- number of iterations\n"
2008-03-05 09:52:00 -05:00
);
}
int main(int argc, char *argv[]) {
2008-11-17 18:29:00 -05:00
int arg;
pthread_args_t blee;
BOOL fNeedHelp = FALSE;
char *argn;
char *argp;
char *address;
DWORD dwPort;
BOOL bHaveAddress;
LARGE_INTEGER before;
LARGE_INTEGER after;
LARGE_INTEGER frequency;
double elapsed;
double rate;
double MBS;
double mbs;
int i;
DWORD dwThreadId;
HANDLE hThread;
InitChildLayer();
endThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
threadCountMutex = CreateMutex(NULL,FALSE,NULL);
doneThreads = 0;
if (endThreadEvent == NULL) {
printf("Unable to allocate event!\n");
exit(1);
}
numThreads = 1;
dwPort = 5000;
iterationCount = 10;
fNeedHelp = FALSE;
bHaveAddress = FALSE;
2008-03-05 09:52:00 -05:00
for (arg = 1; arg < argc && !fNeedHelp; arg++) {
if (argv[arg][0] == '-' || argv[arg][0] == '/') {
argn = argv[arg]+1; // Argument name
argp = argn; // Argument parameter
while (*argp && *argp != ':') {
argp++;
}
if (*argp == ':')
*argp++ = '\0';
switch (argn[0]) {
case '?': // Help
fNeedHelp = TRUE;
break;
2008-11-17 18:29:00 -05:00
case 'a': // address to connect to
2008-03-05 09:52:00 -05:00
case 'A':
address = argp;
2008-11-17 18:29:00 -05:00
printf("Address = '%s'\n", argp);
bHaveAddress = TRUE;
2008-03-05 09:52:00 -05:00
break;
case 'i': // iterations within thread
case 'I':
iterationCount = atoi(argp);
break;
2008-11-17 18:29:00 -05:00
case 'p': // port to attach to
2008-03-05 09:52:00 -05:00
case 'P':
dwPort = (DWORD)atoi(argp);
break;
2008-11-17 18:29:00 -05:00
case 't': // Number of threads to start
2008-03-05 09:52:00 -05:00
case 'T':
numThreads = atoi(argp);
break;
default:
printf("Unknown argument: %s\n", argv[arg]);
fNeedHelp = TRUE;
break;
}
}
else {
}
}
if (fNeedHelp | !bHaveAddress) {
2008-11-17 18:29:00 -05:00
Usage();
exit(1);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
printf ("Connecting to %s on port %d. threads=%d iterations=%d..", address, dwPort, numThreads, iterationCount);
blee = malloc(sizeof(pthread_args_t));
blee->host = address;
blee->port = dwPort;
2008-03-05 09:52:00 -05:00
#if 1
2008-11-17 18:29:00 -05:00
for (i=0; i < numThreads; i++) {
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
MC_DoFetchUrl, // thread function
blee, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
}
//for (i=0; i < numThreads; i++) {
2008-03-05 09:52:00 -05:00
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&before);
2008-11-17 18:29:00 -05:00
while(doneThreads != numThreads ) {
WaitForSingleObject(endThreadEvent,INFINITE);
printf ("received %d of %d events, done=%d\n", i+1, numThreads, doneThreads);
}
2008-03-05 09:52:00 -05:00
QueryPerformanceCounter(&after);
after.QuadPart -= before.QuadPart;
elapsed = (double)after.QuadPart / (double)frequency.QuadPart;
2008-11-17 18:29:00 -05:00
rate = (double) g_totalBytesRead / elapsed;
printf("bytes read =%d, time elapsed = %10.3f seconds rate = %10.3f \n", g_totalBytesRead, elapsed, rate);
MBS = rate / (double) (1024 *1024);
mbs = MBS * 8;
printf("MB/s = %10.3f, mb/s = %10.3f\n", MBS, mbs);
2008-03-05 09:52:00 -05:00
#else
2008-11-17 18:29:00 -05:00
MC_DoFetchUrl(blee);
#endif
WSACleanup( );
2008-03-05 09:52:00 -05:00
}