//udp client
// can work on unix or windows machines
// this program tests the time it takes to transfer a fixed file size by varying the packet size
//#define WIN // WIN for Winsock and BSD for BSD sockets
#define BSD
//note( BSD )
// compile on babbage% g++ -o client client_udp.cpp -lxnet
// compile on redhat % g++ -o client client_udp.cpp
//----- Include files ---------------------------------------------------------
#include < stdio.h> // Needed for printf()
#include < string.h> // Needed for memcpy() and strcpy()
#include < time.h> // timing function
#include < iostream.h> //cout,etc.
#include < fstream.h> //files
#ifdef WIN
#include < windows.h> // Needed for all Winsock stuff
#else
#include < sys/types.h> // Needed for system defined identifiers.
#include < netinet/in.h> // Needed for internet address structure.
#include < sys/socket.h> // Needed for socket(), bind(), etc...
#include < arpa/inet.h> // Needed for inet_ntoa()
#include < sys/time.h> // Needed for timeval{}
#include < fcntl.h>
#include < netdb.h>
#endif
//----- Defines ---------------------------------------------------------------
#define PORT_NUM 1050 // Port number used
#define MESS_SIZE 100000 // Message size, 0.1mbytes
#define REPEAT 5
#define MAX_PACKET_SIZE 10000
//set time out for lost datagram
void setTimeout( int my_s ) ;
//crunch out some numbers
void crunch( int my_s,
const struct sockaddr *pdest_addr,
unsigned int destlen ) ;
//===== Main program ==========================================================
void main(void)
{
unsigned int my_s; // My (client1) socket descriptor
struct sockaddr_in dest_addr; // Server Internet address
struct hostent *myhostent ;
int server_len;
#ifdef WIN
WORD wVersionRequested = MAKEWORD(1,1); // Stuff for WSA functions
WSADATA wsaData; // Stuff for WSA functions
// This stuff initializes winsock
WSAStartup(wVersionRequested, &wsaData);
#endif
// Create a socket
// - AF_INET is Address Family Internet and SOCK_DGRAM is datagram
my_s = socket(AF_INET, SOCK_DGRAM, 0);
/* get internet address */
myhostent = gethostbyname("booboo") ;
server_len = sizeof( dest_addr ) ;
#ifdef WIN
memset( (char *)&dest_addr, 0, server_len ) ;
memcpy( (char *)&dest_addr.sin_addr,
(char *)myhostent->h_addr,
myhostent->h_length ) ;
#else
bzero((char *)&dest_addr, server_len);
bcopy((char *)myhostent->h_addr,
(char *)&dest_addr.sin_addr,
myhostent->h_length);
#endif
dest_addr.sin_family = AF_INET; // Address family to use
dest_addr.sin_port = htons(PORT_NUM); // Port num to use
/* end getting internet address */
/* make sure address if valid */
printf("Sending to %s\n\n", inet_ntoa(dest_addr.sin_addr));
//set timed out to 5 seconds
setTimeout( my_s ) ;
//crunch out the numbers
crunch( my_s,
(struct sockaddr *) &dest_addr,
sizeof( dest_addr ) ) ;
// Close all open sockets (my socket)
#ifdef WIN
closesocket(my_s);
WSACleanup();
#else
close(my_s);
#endif
}
void setTimeout( int my_s )
{
struct timeval tv ;
tv.tv_sec = 2000 ;//2 seconds
tv.tv_usec = 0 ;
#ifdef WIN
setsockopt( my_s,
SOL_SOCKET,
SO_RCVTIMEO,
(char FAR *)&tv,
sizeof( tv ) );
#else //BSD
setsockopt( my_s,
SOL_SOCKET,
SO_RCVTIMEO,
(char *)&tv,
sizeof( tv ) ) ;
#endif
}
void crunch( int my_s,
const struct sockaddr *pdest_addr,
unsigned int destlen )
{
int i, //loop variable
n, //check lost datagrams
packet_size, //another loop variable
changeable_packet,
buffer_left,
lost_packets = 0 ;//count of
long double clock_diff,
total_clock1,
total_clock2 ;
char *sendline = new char[ MAX_PACKET_SIZE ]; // Buffer for output data
char *recvline = new char[ MAX_PACKET_SIZE + 1 ]; // Buffer for output data
clock_t clock1, clock2;
fstream outfile ;
//open file
outfile.open( "outfile_udp.dat", ios::out ) ;
//file header
outfile << "packet_size" << " " << "time( sec )\n\n" ;
memset( sendline, 'a', MAX_PACKET_SIZE ) ;
memset( recvline, '\0', MAX_PACKET_SIZE + 1 ) ;
for( packet_size=8990; packet_size<=MAX_PACKET_SIZE; packet_size++ )
{ //actually, packetsize = 20 ip_header + 8 udp_header + packet_size
clock_diff = 0 ; //reset clocks
for( i=0; i< REPEAT; i++ )//statistically do 5 times
{
total_clock1 = 0;//reset total to zero
total_clock2 = 0;
changeable_packet = packet_size ;
buffer_left = MESS_SIZE ;//will decrease buffer size in do loop
do
{
//sendline[ changeable_packet ] = 0 ;
clock1 = clock() ;//start timer
sendto( my_s, //in sendto, 28, ie 20 + 8, more bytes will be added
sendline,
changeable_packet,
0,
pdest_addr,
destlen ) ;
n = recvfrom( my_s, //receive acknowledgement
recvline,
changeable_packet + 1,
0,
NULL,
NULL ) ;
if( n<0 )//timed out, resend packet
{
cout << "timeout" << endl;
cout << "resending packet " << packet_size << endl;
//for fun, count number of lost packets
lost_packets++ ;
//go back to beginning of do loop
continue ;
}
clock2 = clock() ;//end timer
total_clock1 += (double)clock1 ;
total_clock2 += (double)clock2 ;
buffer_left -= packet_size ;//decrease buffer size
if( buffer_left < packet_size )//update packet
changeable_packet = buffer_left ;
}while( buffer_left > 0 ) ;
//add up 5 times then divide by 5 to get average
clock_diff = clock_diff +( total_clock2 - total_clock1 );
}//end sampling five times
//output to screen
cout << endl
<< "packet_size = " << packet_size
<< " diff in clocks in secs = " << clock_diff / ( REPEAT * CLOCKS_PER_SEC )
<< endl ;
//output to file
outfile << packet_size << " "
<< clock_diff/( REPEAT * CLOCKS_PER_SEC ) << "\n" ;
}//end for loop
cout << "total lost packets... " << lost_packets << endl ;
outfile.close() ;
delete [] sendline ;
delete [] recvline ;
}