open-source-search-engine/thunder.cpp
2013-08-02 13:12:24 -07:00

184 lines
5.2 KiB
C++

// Matt Wells, copyright Sep 2001
#include "gb-include.h"
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/time.h>
// seems like big dgrams are not always liked over the internet
// connection...
#define DGRAM_SIZE 1450
//#define DGRAM_SIZE (30*1492)
//#define DGRAM_SIZE 10000 // this works, but 50,000 does not
long s_n = 0;
long s_isServer = 0;
long s_blast = 0;
long long gettimeofdayInMilliseconds() ;
inline long long gettimeofdayInMilliseconds() {
struct timeval tv;
gettimeofday ( &tv , NULL );
long long now=(long long)(tv.tv_usec/1000)+((long long)tv.tv_sec)*1000;
return now;
}
int main ( int argc , char *argv[] ) {
// ip/port to ask for the file from
long ip = 0;
unsigned short port = 0;
// . filename may be supplied
// . if so we send that file back to all who ask
if ( argc == 2 ) {
// listen on udp port 2000
port = 2000;
s_n = atoi ( argv[1] );
s_isServer = 1;
}
// thunder bytesToSend Port
else if ( argc == 3 ) {
// send on udp port 2001
s_n = atoi ( argv[1] );
port = atoi(argv[2] );
s_isServer = 1;
}
// thunder bytesToSend ip Port
else if ( argc == 4 ) {
// send on udp port 2001
s_n = atoi ( argv[1] );
inet_aton ( argv[2] , (struct in_addr *) &ip );
port = atoi(argv[3]);
s_isServer = 0;
}
// thunder blast bytesToSend ip Port
else if ( argc == 5 && strcmp(argv[1],"blast") == 0 ) {
// send on udp port 2001
s_n = atoi ( argv[2] );
inet_aton ( argv[3] , (struct in_addr *) &ip );
port = atoi(argv[4]);
s_isServer = 0;
s_blast = 1;
}
// otherwise, print usage
else {
fprintf(stderr,
"thunder <bytes-to-send> [port]\n"
"\tThis will set up a server on udp port 2000 which\n"
"\twill serve meaningless bytes to all incoming\n"
"\trequests.\n\n"
"thunder <bytes-to-read> <ip> <port>\n"
"\tThis will send a request for this many bytes to\n"
"\tthe thunder running on the specified ip on port\n"
"\t2000. ip must be of form like 1.2.3.4\n\n"
"thunder blast <bytes-to-send> <ip> <port>\n"
"\tThis will blast the ip port with datagrams.\n"
"\twill serve meaningless bytes to all incoming\n\n"
);
return -1;
}
if ( s_isServer )
fprintf(stderr,"Listening on udp port %hu\n", port );
// set up our socket
int sock = socket ( AF_INET, SOCK_DGRAM , 0 );
if ( sock < 0 ) {
fprintf(stderr,"socket: %s\n",strerror(errno));
return -1;
}
// sockaddr_in provides interface to sockaddr
struct sockaddr_in name;
// reset it all just to be safe
bzero((char *)&name, sizeof(name));
name.sin_family = AF_INET;
name.sin_addr.s_addr = 0; /*INADDR_ANY;*/
name.sin_port = htons(port);
// we want to re-use port it if we need to restart
int options = 1;
if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR ,
&options,sizeof(options)) < 0 ) {
fprintf(stderr,"setsockopt:%s\n", strerror(errno));
return -1;
}
// bind this name to the socket
if ( bind ( sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
close ( sock );
fprintf(stderr,"bind on port %hu: %s\n",port,strerror(errno));
return false;
}
char dgram[DGRAM_SIZE];
int n;
struct sockaddr_in to;
sockaddr_in from;
unsigned int fromLen;
long count = 0;
long long startTime;
long bytes = 0;
char *s;
unsigned long fromport;
//long long took;
// send more than expected to make up for losses
long nn = s_n * 10;
if ( ! s_isServer ) goto doClient;
readLoop:
fromLen = sizeof ( struct sockaddr );
n = recvfrom (sock,dgram,DGRAM_SIZE,0,(sockaddr *)&from, &fromLen);
if ( n <= 0 ) goto readLoop;
s = inet_ntoa(from.sin_addr);
fromport = (unsigned long)ntohs(from.sin_port);
fprintf(stderr,"got request from ip %s:%lu\n",
s,fromport);
to.sin_family = AF_INET;
to.sin_addr.s_addr = from.sin_addr.s_addr;
to.sin_port = from.sin_port; // htons ( 2001 );
bzero ( &(to.sin_zero) , 8 );
memset ( dgram , 'X' , DGRAM_SIZE );
count = 0;
sendLoop:
bytes = s_n;
if ( bytes > (long)DGRAM_SIZE ) bytes = (long)DGRAM_SIZE;
n = sendto(sock,dgram,bytes,0,(struct sockaddr *)&to,sizeof(to));
if ( n != bytes ) fprintf(stderr,"sendto:%s\n",strerror(errno));
else count += n;
//usleep(1);
//fprintf(stderr,"sent %li bytes (of %li)\n",count,s_n);
if ( count < nn ) goto sendLoop;
fprintf(stderr,"finished sending now listening again\n");
goto readLoop;
doClient:
startTime = gettimeofdayInMilliseconds();
to.sin_family = AF_INET;
to.sin_addr.s_addr = ip;
to.sin_port = htons ( port );//2000 ) ; // m_port );
bzero ( &(to.sin_zero) , 8 );
tight:
n = sendto(sock,dgram,DGRAM_SIZE,0,(struct sockaddr *)&to,sizeof(to));
if ( s_blast ) goto tight;
count = 0;
readLoop2:
n = recvfrom (sock,dgram,DGRAM_SIZE,0,(sockaddr *)&from, &fromLen);
if ( n <= 0 ) goto readLoop2;
count += n;
//fprintf(stderr,"read %li bytes (of %li)\n",count,s_n);
if ( count < s_n ) goto readLoop2;
float secs = gettimeofdayInMilliseconds() - startTime;
secs /= 1000.0;
float mb = (float)count * 8.0 / (1024.0*1024.0);
float mbps = mb / secs;
fprintf(stderr,"got %li bytes at %.2f Mbps\n", count , mbps );
return 1;
}