PRPERF.C

/*++ 

Copyright 1994 - 1998 Microsoft Corporation

Module Name: prperf.c


Abstract: This Sample Windows Socket Application demonstrates use of
the AppleTalk PAP Protocol. Both a server and a client
application are included in this source file. The client
app reads a file and sends the contents to the server. The
server writes out the received bytes to another file.


--*/

#include <windows.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>

//
// the following header contains appletalk specific definitions.
// should be included for AppleTalk Windows Socket Applications
//
#include <atalkwsh.h>
#include "prsamp.h"

#define SOCKET_COUNT 32

#define DEF_SERVER_NAME "Windows Adsp"
#define DEF_SERVER_TYPE "Windows Sockets"
#define DEF_SERVER_ZONE "*"
#define BLOCKSIZE 4096

#define DEF_QUEUE_LEN 5
#define ENTITY_LEN 32

CHAR gServerName[ENTITY_LEN] = DEF_SERVER_NAME;
CHAR gServerType[ENTITY_LEN] = DEF_SERVER_TYPE;
CHAR gServerZone[ENTITY_LEN] = DEF_SERVER_ZONE;
CHAR gProtocolName[10] = "ADSP";
INT NumTimes = 5;
CHAR gFileName[256];

LPSTR pServerName = gServerName;
LPSTR pServerType = gServerType;
LPSTR pServerZone = gServerZone;
LPSTR pProtocolName = gProtocolName;
LPSTR pFileName = gFileName;


HANDLE gFileHandle;
WSADATA WsaData;

SYSTEMTIME SystemStartTime;
SYSTEMTIME SystemEndTime;
FILETIME FileTime;

BOOL fFileSpecified = FALSE;
BOOL fVerify = FALSE;
BOOL fRandom = FALSE;
BOOL fRDM = FALSE;

int loop = 1, looptot;
double Throughput, AvgThroughPut, MinThroughPut, MaxThroughPut;

CHAR DataString[] = {"0123456789abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+"};

#define NANOPOWER 1000000000

//#define DEBUG

typedef struct Sock_Info {
int sock_typ;
int prototyp;
SOCKET nsock;
} *PTEST_INFO, test_info;

_cdecl main (IN SHORT argc, IN PSZ argv[])
{

register char p;
register char *ptr;
int i, r;
BOOL fClient = FALSE;
BOOL fServer = FALSE;

for(i = 1; i < argc; i++)
{
p = argv[i][0];

if (p == '/' || p == '-') // option string
{
p = argv[i][1];

switch(tolower(p))
{
case 'n':
ptr = argv[i]+2;
if(*ptr == '\0')
usage();
while(*pServerName++ = *ptr++);
break;
case 't':
ptr = argv[i]+2;
if(*ptr == '\0')
usage();
while(*pServerType++ = *ptr++);
break;
case 'z':
ptr = argv[i]+2;
if(*ptr == '\0')
usage();
while(*pServerZone++ = *ptr++);
break;
case 's':
ptr = argv[i]+2;
if(*ptr != '\0')
usage();
if(fClient == TRUE)
usage();
fServer = TRUE;
break;
case 'c':
ptr = argv[i]+2;
if(*ptr != '\0')
usage();
if(fServer == TRUE)
usage();
fClient = TRUE;
break;
case 'p':
ptr = argv[i]+2;
if(*ptr == '\0')
usage();
while(*pProtocolName++ = *ptr++);
break;
case 'b':
ptr=argv[i]+2;
if(*ptr == '\0')
usage();
NumTimes = atoi(ptr);
break;
case 'f':
ptr = argv[i]+2;
if(*ptr == '\0')
usage();
while(*pFileName++ = *ptr++);
fFileSpecified = TRUE;
break;
case 'l':
ptr = argv[i]+2;
if(*ptr == '\0')
usage();
loop = atoi(ptr);
break;
case 'v':
ptr = argv[i]+2;
if(*ptr != '\0')
usage();
fVerify = TRUE;
break;
case 'r':
ptr = argv[i]+2;
if(*ptr != '\0')
usage();
fRandom = TRUE;
break;
case 'y':
ptr = argv[i]+2;
if(*ptr != '\0')
usage();
fRDM = TRUE;
break;
case '?':
default:
usage();

}
}
else
{
usage();
}

}

#ifdef DEBUG
printf("Server Name %s\n", gServerName);
printf("Server Type %s\n", gServerType);
printf("Server Zone %s\n", gServerZone);
#endif
printf("%s throughput measurement\n", gProtocolName);

if(stricmp(gProtocolName, "ADSP") && stricmp(gProtocolName, "PAP"))
{
printf("Invalid Protocol Specified\n");
exit(1);
}


if(!(fClient || fServer))
usage();

r = WSAStartup(0x0101, &WsaData);
if (r == SOCKET_ERROR)
{
printf("Startup failed!\n");
WSACleanup();
return(0);
}

if(fClient)
{
BOOL DClnt;

looptot = 0;
MaxThroughPut = 0;
AvgThroughPut = 0;
if(fFileSpecified)
printf("Ignoring -f option for client.\n");
while (looptot < loop)
{
DClnt = DoClient();
if(DClnt)
{
if ((looptot == 0) || (MinThroughPut > Throughput))
MinThroughPut = Throughput;

if (MaxThroughPut < Throughput)
MaxThroughPut = Throughput;

AvgThroughPut = ((AvgThroughPut * looptot) + Throughput)
/ (looptot+1);
printf("Loop %2d/%d Throughput Cur/Min/Max/Ave :", ++looptot, loop);
printf(" %6.2f/%6.2f/%6.2f/%6.2f\n\n\n", Throughput,
MinThroughPut,
MaxThroughPut,
AvgThroughPut);
Throughput = 0.0;
}
else
break;
}
}

if(fServer)
DoServer();

WSACleanup();
return(0);
}


/******************************************************************************

Function - DoServer()

Calling Function - main();

Comments - This section of code calls the Server side of the application.

******************************************************************************/


BOOL DoServer()
{
BOOL fRet = FALSE;

do
{

//
// register the name specified on the command line or use the
// defaults.
//

fRet = OpenSocketRegisterAndListen();


}while(FALSE);

return(fRet);

}


/******************************************************************************

Function - OpenSocketRegisterAndListen()

Calling Function - DoServer();

Comments - This section of code controls the Server side of the application.

******************************************************************************/

BOOL OpenSocketRegisterAndListen()
{

int r = 0; // return from socket calls
int pass_no = 1;
BOOL fRet = TRUE;
SOCKET sock, newsock; // SOCKET descriptor
SOCKADDR_AT atalkaddr; // See atalkwsh.h
WSH_REGISTER_NAME nbpname; // structure for registering NBP name
// see atalkwsh.h
fd_set readfds; // fd_set strutture for select call
int addrlen;
PTEST_INFO test;
int sockettype = SOCK_STREAM;
int protocoltype = ATPROTO_ADSP;
int NumBytesRecvd = 0;
unsigned long ThreadId;





//
// open a appletalk socket. The protocol family should be AF_APPLETALK,
// the socket type can be SOCK_STREAM or SOCK_RDM, and the ProtocolType
// for PAP socket must be ATPROTO_PAP. Note that opening a socket does
// not yet create an endpoint on the AppleTalk Protocol. A bind must
// happen before this socket can be used with AppleTalk;
//

do
{
if(!stricmp(gProtocolName, "PAP"))
{
sockettype = SOCK_RDM;
protocoltype = ATPROTO_PAP;
}
else if (fRDM)
sockettype = SOCK_RDM;


sock = socket(AF_APPLETALK, sockettype, protocoltype);

if(sock == INVALID_SOCKET)
{
printf("Open Socket: Error = %ld\n", WSAGetLastError());
r = -1;
break;
}

atalkaddr.sat_socket = 0;
atalkaddr.sat_family = AF_APPLETALK;

r = bind(sock, (struct sockaddr *)&atalkaddr, sizeof(SOCKADDR_AT));

if(r < 0)
{
printf("Bind:Error = %d\n", WSAGetLastError());
break;
}

//
// end point has now been created on the AppleTalk Protocol
// now register the name that the client will look up.
//

strcpy(nbpname.ObjectName, gServerName);
nbpname.ObjectNameLen = strlen(gServerName);

strcpy(nbpname.TypeName, gServerType);
nbpname.TypeNameLen = strlen(gServerType);

strcpy(nbpname.ZoneName, "*");
nbpname.ZoneNameLen = strlen("*");

printf("Registering %s:%s@%s\n", nbpname.ObjectName,
nbpname.TypeName,
nbpname.ZoneName);


r = setsockopt(sock, // socket descriptor
SOL_APPLETALK, // socket level - always SOL_APPLETALK
SO_REGISTER_NAME, // socket option
(char *)&nbpname, // nbp name structure
sizeof(WSH_NBP_NAME)); // size of nbp name structure


if(r < 0)
{
printf("Register Name: Error = %d\n", WSAGetLastError());
break;
}

}while(FALSE);

if(r == SOCKET_ERROR)
{
closesocket(sock);
return(FALSE);
}

//
// Post a listen on this socket. The default queue length is 5
//

r = listen(sock, DEF_QUEUE_LEN);

if(r < 0)
{
printf("Listen:Error = %d\n", WSAGetLastError());
return FALSE;
}


//
// listen is successful. select the socket for reading
//

do
{

FD_ZERO(&readfds); // clear set
FD_SET(sock, &readfds); // add sock to set

//
// this is a blocking select. Select will complete when
// a client connects.
//

r = select(0, &readfds, NULL, NULL, NULL);

if(r == SOCKET_ERROR)
{
printf("Select: Error = %d\n", WSAGetLastError());
fRet = FALSE;
break;
}

if ( r == 0)
{
printf("Select: no sockets available\n");
fRet = FALSE;
break;
}

//
// Accept an incoming request.
//

addrlen = sizeof(SOCKADDR_AT);
newsock = accept(sock, (struct sockaddr *)&atalkaddr, &addrlen);

if(newsock == INVALID_SOCKET)
{
printf("Accept: Socket Error = %d\n", WSAGetLastError());

fRet = FALSE;
break;
}

#ifdef DEBUG
// printf("Accept Succeeded\n");
#endif


if(r == SOCKET_ERROR)
{
fRet = FALSE;
break;
}


test = (PTEST_INFO) LocalAlloc(LPTR, sizeof(test_info));
test->sock_typ = sockettype;
test->prototyp = protocoltype;
test->nsock = newsock;

if( ! CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PerfThread,
(PTEST_INFO) test, 0, & ThreadId ) )
{
fprintf(stderr,"CreateThread NULL 0 PerfThread %d 0 %d 0 %lx",
test->sock_typ, test->prototyp, (unsigned long) & ThreadId);
exit(1);
}

if (fRet == FALSE)
break;

}while (TRUE);


closesocket(sock);

//
// send all done
//

return(TRUE);

}


/******************************************************************************

Function - PerfThread()

Calling Function - OpenSocketRegisterAndListen();

Comments - This section of code controls the Server side Recieve and Verification
for the application.

******************************************************************************/


unsigned long PerfThread( PTEST_INFO lpvTest )
{
int r; // return from socket calls
int recvflags = 0; // see WSARecvEx call
CHAR recvbuf[4096]; // recv buffer
long blockmode = 1; // see ioctlsocket call
BOOL fRet = TRUE;
int NumBytesRecvd = 0, pass_no = 1;
SOCKET newsock = lpvTest->nsock; // SOCKET descriptor
int sockettype = lpvTest->sock_typ;
int protocoltype = lpvTest->prototyp;

//
// make socket non blocking. As far as possible, use non
// blocking sockets to improve performance of app.
//
//

r = ioctlsocket(newsock, FIONBIO, &blockmode);

if( r == SOCKET_ERROR)
{
printf("ioctlsocket: error = %d\n", WSAGetLastError());
fRet = FALSE;
return(FALSE);
}

do
{


//
// Prime a Read here. This will enable the receive to complete
// This is PAP specific. For other AppleTalk protocols -
// ADSP and DDP a recv can be posted directly
//

if(!stricmp(gProtocolName, "PAP"))
{

r = setsockopt(newsock,
SOL_APPLETALK,
SO_PAP_PRIME_READ,
recvbuf,
sizeof(recvbuf));

if( r < 0)
{
printf("primeread: error = %d\n", WSAGetLastError());
fRet = FALSE;
break;

}
}

fRet = CheckForRecv(newsock);

if(fRet == FALSE)
break;

r = WSARecvEx(newsock,recvbuf,sizeof(recvbuf), &recvflags);


if ((sockettype == SOCK_RDM) && (r < sizeof(recvbuf)))
{
printf("Did not receive entire message\n");
fRet = FALSE;
break;
}

if( r == SOCKET_ERROR)
{

if (WSAGetLastError() == WSAEWOULDBLOCK)
continue;
else
{
if(WSAGetLastError() == WSAENOTCONN || WSAGetLastError() == WSAEFAULT)
break;
printf("recv: error = %d\n", WSAGetLastError());
fRet = FALSE;
break;
}

}

#ifdef DEBUG
// printf("Recvd %d bytes\n", r);
#endif

if (fVerify)
{
int rr, pos = 0;


do
{
fRet = CheckForSend(newsock);

if (fRet == FALSE)
{
printf("send select error\n");
break;
}

rr = send(newsock, &recvbuf[pos], r-pos, 0);

if ( rr < 0 )
{
if(WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("Send: error = WSAEWOULDBLOCK\n");
continue;
}
else
{
printf("send: error = %d\n", WSAGetLastError());
break;
}

}

#ifdef DEBUG
// printf("Bytes Sent %d\n", rr);
#endif

pos += rr;

if (pos >= r)
break;

} while(TRUE);

} // endif Verify


NumBytesRecvd += r;

//
// reset the recv flags for the next WSARecvEx
//
recvflags = 0;

}while(TRUE);

printf("Total Number of Bytes Received = %d \n",NumBytesRecvd);

closesocket(newsock);
LocalFree(lpvTest);

return(TRUE);
}

/******************************************************************************

Function - DoClient()

Calling Function - main();

Comments - This section of code controls the Client side of the application.

******************************************************************************/

BOOL DoClient()
{
int r = 0; // return code
BOOL fRet = FALSE; //
int charcnt; // count of bytes read from file
CHAR LookupBuffer[512]; // LookUp results return buffer
PCHAR ptupleBuffer;
PWSH_LOOKUP_NAME pLookup;
PWSH_NBP_TUPLE pTempTuple;
SOCKADDR_AT ataddress;
DWORD WrittenSize;
SOCKET clntsock;
long blockmode = 1; // for ioctlsocket
int BytesTransferred = 0;
HLOCAL memhandle;
LPSTR DataPtr, DataStartPtr, DataEndPtr;
DWORD hourdiff; //, minutediff, seconddiff;
double StartSecond, EndSecond,ElapsedSeconds;
int sockettype = SOCK_STREAM;
int prototype = ATPROTO_ADSP;
int i, rndbuf;

if(!stricmp(gProtocolName, "PAP"))
{
sockettype = SOCK_RDM;
prototype = ATPROTO_PAP;
}
else if (fRDM)
sockettype = SOCK_RDM;

if (fRandom)
rndbuf = rand() % strlen(DataString) + 1;
else
rndbuf = strlen(DataString);

do
{
//
// See socket call in OpenSocketRegisterAndListen for desc
//
clntsock = socket(AF_APPLETALK, sockettype, prototype);

if(clntsock == INVALID_SOCKET)
{
printf("Open Socket: Error = %ld\n", WSAGetLastError());
r = -1;
break;

}

ataddress.sat_socket = 0;
ataddress.sat_family = AF_APPLETALK;


r = bind(clntsock, (struct sockaddr *)&ataddress, sizeof(SOCKADDR_AT));

if(r < 0)
{
printf("Bind:Error = %d\n", WSAGetLastError());
break;
}

//
// end point has now been created on the AppleTalk Protocol.
// lookup the server name.
//


pLookup = (PWSH_LOOKUP_NAME)LookupBuffer;

strcpy(pLookup->LookupTuple.NbpName.ObjectName, gServerName);
pLookup->LookupTuple.NbpName.ObjectNameLen = strlen(gServerName);

strcpy(pLookup->LookupTuple.NbpName.TypeName, gServerType);
pLookup->LookupTuple.NbpName.TypeNameLen = strlen(gServerType);

strcpy(pLookup->LookupTuple.NbpName.ZoneName, gServerZone);
pLookup->LookupTuple.NbpName.ZoneNameLen = strlen(gServerZone);

#ifdef DEBUG
printf("Looking up %s:%s@%s\n",pLookup->LookupTuple.NbpName.ObjectName,
pLookup->LookupTuple.NbpName.TypeName,
pLookup->LookupTuple.NbpName.ZoneName);
#endif

WrittenSize = sizeof(LookupBuffer);

r = getsockopt(clntsock, SOL_APPLETALK, SO_LOOKUP_NAME,
(char*)LookupBuffer,
&WrittenSize);

if(r != NO_ERROR)
{
printf("getsockopt:error = %d\n", WSAGetLastError());
break;

}

if (pLookup->NoTuples <= 0)
{
printf("LookupName failed - no tuples found\n");
r=-1;
break;
}

ptupleBuffer = (char *)pLookup+sizeof(WSH_LOOKUP_NAME);
pTempTuple = (PWSH_NBP_TUPLE)ptupleBuffer;

ataddress.sat_family = AF_APPLETALK;
ataddress.sat_net = pTempTuple[0].Address.Network;
ataddress.sat_node = pTempTuple[0].Address.Node;
ataddress.sat_socket = pTempTuple[0].Address.Socket;

#ifdef DEBUG
printf("server address = %lx.%lx.%lx.\n", ataddress.sat_net,
ataddress.sat_node,
ataddress.sat_socket);
#endif


//
// lookup succeeded. Use the address in ataddress to connect to the
// server
//

r = connect(clntsock, (struct sockaddr *)&ataddress, sizeof(SOCKADDR_AT));

if(r < 0)
{
printf("connect: error = %d\n", WSAGetLastError());
break;
}

#ifdef DEBUG
// printf("Connect Succeeded\n");
#endif


}while(FALSE);

if(r < 0)
{
closesocket(clntsock);
return(FALSE);
}

//
// Set Socket to non blocking mode
//

r = ioctlsocket(clntsock, FIONBIO, &blockmode);

#ifdef DEBUG
// printf("ioctlsocket Succeeded\n");
#endif

if( r == SOCKET_ERROR)
{
printf("ioctlsocket: error = %d\n", WSAGetLastError());
return FALSE;
}

//
// Fill Up Send Buffer with Data
//
memhandle = LocalAlloc(LPTR, BLOCKSIZE);
if(memhandle == NULL)
{
printf("LocalAlloc Failed %d\n", GetLastError());
return(FALSE);
}
DataPtr = LocalLock(memhandle);
DataStartPtr = DataPtr;
DataEndPtr = DataPtr + LocalSize(memhandle);

//
// fill the buffer with Data
//
while((DataStartPtr + rndbuf) <= DataEndPtr)
{
memcpy(DataStartPtr, DataString,rndbuf);
DataStartPtr+= rndbuf;
}

if(DataStartPtr != DataEndPtr)
memcpy(DataStartPtr, DataString, DataEndPtr-DataStartPtr-1);

*DataEndPtr = '\0';

fRet = CheckForSend(clntsock);

if(fRet == FALSE)
return FALSE;

GetLocalTime(&SystemStartTime);

#ifdef DEBUG
printf("Data Size = %d\n", lstrlen(DataPtr));
// printf("Base Data sent: %s\n",DataStartPtr);
printf("Start Time:%d:%2d:%2d:%2d\t", SystemStartTime.wHour,
SystemStartTime.wMinute,
SystemStartTime.wSecond,
SystemStartTime.wMilliseconds);
#endif

for( i= 0; i < NumTimes; i++)
{
//
// Can I send - CheckForSend calls select to find if we can send
// without blocking
//
DataStartPtr = DataPtr;

do
{
fRet = CheckForSend(clntsock);

if(fRet == FALSE)
{
printf("send select error\n");
break;
}

charcnt = DataEndPtr - DataStartPtr;

if(charcnt == 0)
break;

r = send(clntsock, DataStartPtr, charcnt, 0);


if ( r < 0 )
{

if(WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("send: wouldblock\n");
continue;
}
else
{
printf("send: error = %d\n", WSAGetLastError());
fRet = FALSE;
break;
}

}
else
{

#ifdef DEBUG
// printf("Sent %d bytes\n",r);
#endif

if ((fVerify) && (DataStartPtr + r == DataEndPtr))
{
CHAR buffer[4096];
int recvflag = 0;
int rr, pos = 0;

//
// Prime a Read here. This will enable the receive to complete
// This is PAP specific. For other AppleTalk protocols -
// ADSP and DDP a recv can be posted directly
//

if(!stricmp(gProtocolName, "PAP"))
{

rr = setsockopt(clntsock,
SOL_APPLETALK,
SO_PAP_PRIME_READ,
buffer,
sizeof(buffer));

if( rr < 0)
{
printf("primeread: error = %d\n", WSAGetLastError());
fRet = FALSE;
break;
}
}

do
{

fRet = CheckForRecv(clntsock);

if(fRet == FALSE)
break;

rr = WSARecvEx(clntsock, &buffer[pos], sizeof(buffer)-pos, &recvflag);

if( rr == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
continue;
else
{
printf("recv: error = %d\n", WSAGetLastError());
fRet = FALSE;
break;
}
}

pos += rr;

#ifdef DEBUG
// printf("Recv'd %d bytes\n",rr);
#endif

if ((recvflag == 0) || (sockettype == SOCK_RDM) ||
(pos == sizeof(buffer)))
break;
recvflag = 0;

} while(TRUE);


if ((memcmp(DataPtr, buffer, 4096) != 0) && (fRet != FALSE))
{
printf("Strings do not compare\n");
#ifdef DEBUG
// printf("Data sent: \n%s\n",DataPtr);
// printf("Data recv'd: \n%s\n",buffer);
#endif

}


} // IF (fVerify)

BytesTransferred += r;
DataStartPtr += r;

if(DataStartPtr == DataEndPtr)
break;

} // IF send() PASSED

}while(TRUE);

if(fRet == FALSE)
break;

} // FOR

GetLocalTime(&SystemEndTime);

#ifdef DEBUG
printf("End Time:%d:%2d:%2d:%2d\t", SystemEndTime.wHour,
SystemEndTime.wMinute,
SystemEndTime.wSecond,
SystemEndTime.wMilliseconds);
#endif

//
// calculate the difference
//

hourdiff = SystemEndTime.wHour - SystemStartTime.wHour;

StartSecond = (SystemStartTime.wHour * 3600) +
(SystemStartTime.wMinute * 60) +
SystemStartTime.wSecond +
(SystemStartTime.wMilliseconds * 0.001);

EndSecond = 0;

if(SystemEndTime.wMonth != SystemStartTime.wMonth)
{
EndSecond = (SystemEndTime.wDay * 24) * 3600;
switch (SystemStartTime.wMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
EndSecond = ((31 - SystemStartTime.wDay) * 24) + EndSecond;
break;
case 4:
case 6:
case 9:
case 11:
EndSecond = ((30 - SystemStartTime.wDay) * 24) + EndSecond;
break;
case 2:
if((SystemStartTime.wYear % 400 == 0) ||

((SystemStartTime.wYear % 4 == 0) && 
(SystemStartTime.wYear % 100 != 0)))
EndSecond = ((29 - SystemStartTime.wDay) *
24) + EndSecond;
else
EndSecond = ((28 - SystemStartTime.wDay) *
24) + EndSecond;
break;
}
}
else
if(SystemEndTime.wDay > SystemStartTime.wDay)
{
EndSecond = ((SystemEndTime.wDay - SystemStartTime.wDay) * 24) * 3600;
}

EndSecond = EndSecond + (SystemEndTime.wHour * 3600) +
(SystemEndTime.wMinute * 60) + SystemEndTime.wSecond +
(SystemEndTime.wMilliseconds * 0.001);

ElapsedSeconds = EndSecond-StartSecond;

#ifdef DEBUG
printf("Elapsed Time (secs) = %6.3f\n", ElapsedSeconds);
printf("Bytes Transferred = %ld\n", BytesTransferred);
printf("Send All Done\n");
#endif


if(ElapsedSeconds !=0)
{
Throughput = (BytesTransferred)/(ElapsedSeconds) ;

#ifdef DEBUG
printf("Throughput (bytes/sec) = %6.2f\n", Throughput);
#endif

}

printf("\n");

closesocket(clntsock);

LocalFree(memhandle);
return(TRUE);

}



BOOL CheckForSend(SOCKET s)
{

fd_set writefds;
int r;


#ifdef DEBUG
printf("\t\tChecking for Send..\n");
#endif

FD_ZERO(&writefds);
FD_SET(s, &writefds);

//
// indefinite wait select
//
r = select(0, NULL, &writefds, NULL, NULL);

if( r != 1)
{
printf("select:error = %d\n", WSAGetLastError());
return(FALSE);
}
return(TRUE);
}



BOOL CheckForRecv(SOCKET s)
{

fd_set readfds;
int r;

FD_ZERO(&readfds);
FD_SET(s, &readfds);

#ifdef DEBUG
printf("\t\tChecking for Recv..\n");
#endif

r = select(0, &readfds, NULL, NULL, NULL);

if( r != 1)
{
printf("select:error = %d\n", WSAGetLastError());
return(FALSE);
}
return(TRUE);
}

void usage()
{

printf("prperf -s/c <options>\n");
printf("\t-s/c\t Server/Client\n");
printf("\t-n\t Server Name\n");
printf("\t-t\t Server Type \n");
printf("\t-z\t Server Zone \n");
printf("\t-p\t Protocol Name (ADSP/PAP)\n");
printf("\t-f\t File Name for data to be saved (server only) \n");
printf("\t-b\t Number of times to send a 4k buffer (Default = 5) \n");
printf("\t-l\t Number of times to re-start prperf (Default = 1) (Client only)\n");
printf("\t-v\t Verify Integraty of data transmission. \n");
printf("\t-r\t Randomize the size of the base data string. \n");
printf("\t-y\t Change ADSP to use SOCK_RDM instead of SOCK_STREAM. \n");
printf("\n");
exit(1);

}