tcpblast.c
上传用户:shbosideng
上传日期:2013-05-04
资源大小:1555k
文件大小:7k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /* From FreeBSD: */
  2. /*
  3.  *      tcpblast - test and estimate TCP thruput
  4.  *
  5.  *      Daniel Karrenberg   <dfk@nic.eu.net>
  6.  */
  7. /*
  8.  * Changes: Rafal Maszkowski <rzm@pdi.net>
  9.  *
  10.  * ftp://ftp.torun.pdi.net/pub/blast/README
  11.  */
  12. char *verstr="FreeBSD + rzm 961003";
  13. #include <getopt.h>
  14. #include <netdb.h>
  15. #include <netinet/in.h>
  16. #include <arpa/inet.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <sys/file.h>
  21. #include <sys/socket.h>
  22. #include <sys/time.h>
  23. #include <sys/types.h>
  24. #include <unistd.h>
  25. #define DEFBLKSIZE (1024)
  26. #define MAXBLKSIZE (32*1024)
  27. struct sockaddr_in sock_in;
  28. struct servent *sp;
  29. struct hostent *host;
  30. unsigned long starts, startms, stops, stopms, expms;
  31. struct timeval ti; 
  32. struct timezone tiz;
  33. char  greet[MAXBLKSIZE], *ind;
  34. int  nblocks, f;
  35. int tcp=0, udp=0, randomb=0, blksize=DEFBLKSIZE, setbufsize=-1, port=9, dots=1;
  36. /* Long options.  */
  37. static const struct option long_options[] =
  38. {
  39.   { "help", no_argument, NULL, 'h' },
  40.   { "version", no_argument, NULL, 'V' },
  41.   { NULL, 0, NULL, 0 }
  42. };
  43. void usage(name)
  44. char *name;
  45. {
  46. fprintf(stderr, "n");
  47. fprintf(stderr, "usage: %s [options] destination nblocksnn", name);
  48. fprintf(stderr, "tcpblast/udpblast is a simple tool for probing network and estimating itsn");
  49. fprintf(stderr, "throughoutput. It sends nblocks of %d B blocks of data to specifiedn", blksize);
  50. fprintf(stderr, "destination hostnn");
  51. fprintf(stderr, "Options:n");
  52. fprintf(stderr, "-t             use TCP (%s)n", ind[0]=='t' ? "default" : "default if named tcpblast" );
  53. fprintf(stderr, "-u             use UDP (%s)n", ind[0]=='u' ? "default" : "default if named udpblast" );
  54. fprintf(stderr, "-p nnn         use port # nnn instead of default %dn", port);
  55. fprintf(stderr, "-r             send random datan");
  56. fprintf(stderr, "-s nnn         block size (default %d bytes)n", blksize);
  57. fprintf(stderr, "-b nnn         socket buf size (default: %d, %s)n", setbufsize, setbufsize==-1 ? "don't change" : "change");
  58. fprintf(stderr, "-d nnn         print dot every nnn blocks, 0 disables (default %d)n", dots);
  59. fprintf(stderr, "-V, --version  versionn");
  60. fprintf(stderr, "-h, --help     this helpn");
  61. fprintf(stderr, "destination    host name or addressn");
  62. fprintf(stderr, "nblocks        number of blocks (1..9999)n");
  63. fprintf(stderr, "%s version: %sn", name, verstr);
  64. exit(1);
  65. }
  66. void usage_small(name)
  67. char *name;
  68. {
  69. fprintf(stderr, "type %s --help for helpn", name);
  70. }
  71. /* randomize the buffer */
  72. void
  73. randbuff(blksize) 
  74. int blksize;
  75. {
  76. int i;
  77. for (i=0; i<blksize; i++) {
  78. greet[i]=rand() % 256;
  79. }
  80. }
  81. int
  82. main(argc, argv)
  83.      int argc;
  84.      char **argv;
  85. { register int i; char optchar;
  86. /* non-random data - is modem compressing it? */
  87. bzero(greet, MAXBLKSIZE);
  88. memset(greet, 'a', MAXBLKSIZE); 
  89. /* find first letter in the name - usage() needs it */
  90. ind=rindex(argv[0], '/');
  91. if (ind==NULL) ind=argv[0]; else ind++;
  92. while ((optchar = getopt_long (argc, argv, "tup:rs:b:d:Vh", long_options, NULL)) != EOF)
  93. switch (optchar) {
  94. case '': break;
  95. case 't': if (tcp==0) tcp=1; break;
  96. case 'u': if (udp==0) udp=1; break;
  97. case 'r': srand(0 /* may be an option */); randomb=1; break;
  98. case 's': blksize=abs(atoi(optarg)); break;
  99. case 'b': setbufsize=abs(atoi(optarg)); break;
  100. case 'd': dots=abs(atoi(optarg)); break;
  101. case 'p': port=abs(atoi(optarg)); break;
  102. case 'V': printf("%s version: %sn", argv[0], verstr); return 0; break;
  103. case 'h': usage(argv[0]);
  104. default: ;
  105. }
  106. /* correctness */
  107. if (tcp && udp) {
  108. printf("cannot use both TCP and UDPn");
  109. usage_small(argv[0]);
  110. exit(2);
  111. }
  112. /* if neither -t nor -u is chosen use first character of the
  113.    program name */
  114. if ( (tcp==0) && (udp==0) && (ind[0]=='t') ) tcp=1;
  115. if ( (tcp==0) && (udp==0) && (ind[0]=='u') ) udp=1;
  116. if (!tcp && !udp) {
  117. printf("must use either TCP or UDPn");
  118. usage_small(argv[0]);
  119. exit(3);
  120. }
  121. /* after options processing we need two args left */
  122. if (argc - optind != 2) {
  123. if (argc - optind != 0) printf("give both hostname and block countn");
  124. usage_small(argv[0]);
  125. exit(4);
  126. }
  127. nblocks = atoi(argv[optind+1]);
  128.         if (nblocks<=0 || nblocks>=10000) {
  129. fprintf(stderr, "%s: 1 < nblocks <= 9999 n", argv[0]);
  130. exit(5);
  131. }
  132. bzero((char *)&sock_in, sizeof (sock_in));
  133. sock_in.sin_family = AF_INET;
  134. if (tcp) f = socket(AF_INET, SOCK_STREAM, 0);
  135. else     f = socket(AF_INET, SOCK_DGRAM, 0);
  136. if (f < 0) {
  137. perror("tcp/udpblast: socket");
  138. exit(6);
  139. }
  140. { unsigned int bufsize, size;
  141. /* get/setsockopt doesn't return any error really for SO_SNDBUF,
  142.    at least on Linux, it limits the buffer only [256..65536] */
  143. if (getsockopt(f, SOL_SOCKET, SO_SNDBUF, &bufsize, &size)==-1)
  144. printf("tcp/udpblast getsockopt: %s", strerror(errno));
  145. printf("read SO_SNDBUF = %dn", bufsize);
  146. if (setbufsize!=-1) {
  147. if (setsockopt(f, SOL_SOCKET, SO_SNDBUF, &setbufsize, sizeof(setbufsize))==-1)
  148. printf("tcp/udpblast getsockopt: %s", strerror(errno));
  149. if (getsockopt(f, SOL_SOCKET, SO_SNDBUF, &bufsize, &size)==-1)
  150. printf("tcp/udpblast getsockopt: %s", strerror(errno));
  151. printf("set  SO_SNDBUF = %dn", bufsize);
  152. }
  153. }
  154. if (bind(f, (struct sockaddr*)&sock_in, sizeof (sock_in)) < 0) {
  155. perror("tcp/udpblast: bind");
  156. exit(7);
  157. }
  158. host = gethostbyname(argv[optind]);
  159. if (host) {
  160. sock_in.sin_family = host->h_addrtype;
  161. bcopy(host->h_addr, &sock_in.sin_addr, host->h_length);
  162. } else {
  163. sock_in.sin_family = AF_INET;
  164. sock_in.sin_addr.s_addr = inet_addr(argv[optind]);
  165. if (sock_in.sin_addr.s_addr == -1) {
  166. fprintf(stderr, "%s: %s unknown hostn", argv[0], argv[optind]);
  167. exit(8);
  168. }
  169. }
  170. sock_in.sin_port = htons(port);
  171. if (connect(f, (struct sockaddr*)&sock_in, sizeof(sock_in)) <0)
  172. {
  173. perror("tcp/udpblast connect:");
  174. exit(9);
  175. }
  176. printf("Sending %s %s data using %d B blocks.n",
  177. randomb ? "random":"non-random", tcp ? "TCP":"UDP", blksize);
  178. if (gettimeofday(&ti, &tiz) < 0)
  179. {
  180. perror("tcp/udpblast time:");
  181. exit(10);
  182. }
  183. starts  = ti.tv_sec;
  184. startms = ti.tv_usec / 1000L;
  185. for (i=0; i<nblocks; i++)
  186. {
  187. if (randomb) randbuff(blksize);
  188. if (write(f, greet, (size_t)blksize) != blksize)
  189. perror("tcp/udpblast send:");
  190. if ( (dots!=0) && ( (dots==1) || (i%dots==1) ) ) write(1, ".", 1);
  191. }
  192. if (gettimeofday(&ti, &tiz) < 0)
  193. {
  194. perror("tcp/udpblast time:");
  195. exit(11);
  196. }
  197. stops  = ti.tv_sec;
  198. stopms = ti.tv_usec / 1000L;
  199. expms = (stops-starts)*1000 + (stopms-startms);
  200. printf("n%d KB in %ld msec", (nblocks*blksize)/1024, expms);
  201. printf("  =  %.1f b/s", ((double) (nblocks*blksize))/expms*8000);
  202. printf("  =  %.1f B/s", ((double) (nblocks*blksize))/expms*1000);
  203. printf("  =  %.1f KB/sn", 
  204. (double) (nblocks*blksize) / (double) (expms*1024.0) * 1000 );
  205. return(0);
  206. }