home *** CD-ROM | disk | FTP | other *** search
/ PC World 2004 November / PCWorld_2004-11_cd.bin / software / vyzkuste / naradi / naradi2.exe / hwutil2 / Netio / Netio.exe / netio.c < prev    next >
C/C++ Source or Header  |  2003-09-30  |  36KB  |  1,742 lines

  1. /* netio.c
  2.  *
  3.  * Author:  Kai-Uwe Rommel <rommel@ars.de>
  4.  * Created: Wed Sep 25 1996
  5.  */
  6.  
  7. static char *rcsid =
  8. "$Id: netio.c,v 1.23 2003/09/30 09:32:22 Rommel Exp Rommel $";
  9. static char *rcsrev = "$Revision: 1.23 $";
  10.  
  11. /*
  12.  * $Log: netio.c,v $
  13.  * Revision 1.23  2003/09/30 09:32:22  Rommel
  14.  * corrections from Matthias Scheler for error handling
  15.  * added socket buffer size setting
  16.  * added htonl/ntohl code (hint from Oliver Lau)
  17.  * restructured send/recv error/result checking
  18.  * more verbose server side messages
  19.  * other minor changes
  20.  *
  21.  * Revision 1.22  2003/09/22 14:58:33  Rommel
  22.  * added server side progress messages
  23.  *
  24.  * Revision 1.21  2003/08/28 12:44:11  Rommel
  25.  * fixed display of non-k-multiple packet sizes
  26.  *
  27.  * Revision 1.20  2003/08/27 11:05:48  Rommel
  28.  * allow block size specifikation in bytes or k bytes
  29.  *
  30.  * Revision 1.19  2003/08/17 16:53:45  Rommel
  31.  * added Unix/Linux pthreads support (required for UDP)
  32.  *
  33.  * Revision 1.18  2003/08/17 14:46:17  Rommel
  34.  * added UDP benchmark
  35.  * several minor changes (cleanup)
  36.  * configurable binding address
  37.  *
  38.  * Revision 1.17  2003/07/12 17:25:00  Rommel
  39.  * made block size selectable
  40.  *
  41.  * Revision 1.16  2003/02/10 09:06:59  Rommel
  42.  * fixed sender algorithm
  43.  *
  44.  * Revision 1.15  2001/09/17 13:56:40  Rommel
  45.  * changed to perform bidirectional benchmarks
  46.  *
  47.  * Revision 1.14  2001/04/19 12:20:55  Rommel
  48.  * added fixes for Unix systems
  49.  *
  50.  * Revision 1.13  2001/03/26 11:37:41  Rommel
  51.  * avoid integer overflows during throughput calculation
  52.  *
  53.  * Revision 1.12  2000/12/01 15:57:57  Rommel
  54.  * *** empty log message ***
  55.  *
  56.  * Revision 1.11  2000/03/01 12:21:47  rommel
  57.  * fixed _INTEGRAL_MAX_BITS problem for WIN32
  58.  *
  59.  * Revision 1.10  1999/10/28 17:36:57  rommel
  60.  * fixed OS/2 timer code
  61.  *
  62.  * Revision 1.9  1999/10/28 17:04:12  rommel
  63.  * fixed timer code
  64.  *
  65.  * Revision 1.8  1999/10/24 19:08:20  rommel
  66.  * imported DOS support from G. Vanem <giva@bgnett.no>
  67.  *
  68.  *
  69.  * Revision 1.8  1999/10/12 11:02:00  giva
  70.  * added Watt-32 with djgpp support. Added debug mode.
  71.  * G. Vanem <giva@bgnett.no>
  72.  *
  73.  * Revision 1.7  1999/06/13 18:42:25  rommel
  74.  * added Linux port with patches from Detlef Plotzky <plo@bvu.de>
  75.  *
  76.  * Revision 1.6  1998/10/12 11:14:58  rommel
  77.  * change to malloc'ed (and tiled) memory for transfer buffers
  78.  * (hint from Guenter Kukkukk <kukuk@berlin.snafu.de>)
  79.  * for increased performance
  80.  *
  81.  * Revision 1.5  1998/07/31 14:15:03  rommel
  82.  * added random buffer data
  83.  * fixed bugs
  84.  *
  85.  * Revision 1.4  1997/09/12 17:35:04  rommel
  86.  * termination bug fixes
  87.  *
  88.  * Revision 1.3  1997/09/12 12:00:15  rommel
  89.  * added Win32 port
  90.  * (tested for Windows NT only)
  91.  *
  92.  * Revision 1.2  1997/09/12 10:44:22  rommel
  93.  * added TCP/IP and a command line interface
  94.  *
  95.  * Revision 1.1  1996/09/25 08:42:29  rommel
  96.  * Initial revision
  97.  *
  98.  */
  99.  
  100. #ifdef WIN32
  101. #define _INTEGRAL_MAX_BITS 64
  102. #endif
  103.  
  104. #include <stdio.h>
  105. #include <stdlib.h>
  106. #include <string.h>
  107. #include <ctype.h>
  108. #include <signal.h>
  109. #if defined(UNIX) || defined(DJGPP)
  110. #include <sys/time.h>
  111. #include <unistd.h>
  112. #include <errno.h>
  113. #else
  114. #include <process.h>
  115. #include "getopt.h"
  116. #include "netbios.h"
  117. #endif
  118.  
  119. #define DEFAULTPORT 0x494F /* "IO" */
  120. #define DEFAULTNBSRV "NETIOSRV"
  121. #define DEFAULTNBCLT "NETIOCLT"
  122. #define THREADSTACK 65536
  123.  
  124. /* TCP/IP system specific details */
  125.  
  126. #ifdef OS2
  127.  
  128. #define BSD_SELECT
  129. #include <types.h>
  130. #include <netinet/in.h>
  131. #include <sys/select.h>
  132. #include <sys/socket.h>
  133. #include <sys/time.h>
  134. #include <netdb.h>
  135.  
  136. #ifdef __IBMC__
  137. #define newthread(entry) (_beginthread(entry, 0, THREADSTACK, 0) == -1)
  138. #else
  139. #define newthread(entry) (_beginthread(entry, THREADSTACK, 0) == -1)
  140. #endif
  141. #define THREAD void
  142.  
  143. #endif /* OS2 */
  144.  
  145. #ifdef WATT32
  146.  
  147. #include <tcp.h>       /* sock_init() etc. */
  148. #include <netinet/in.h>
  149. #include <sys/socket.h>
  150. #include <netdb.h>
  151. #define soclose     close_s
  152. #define select      select_s
  153. #define psock_errno perror
  154.  
  155. #endif /* WATT32 */
  156.  
  157. #ifdef WIN32
  158.  
  159. #include <windows.h>
  160. #include <winsock.h>
  161. #define soclose closesocket
  162.  
  163. int sock_init(void)
  164. {
  165.   WSADATA wsaData;
  166.   return WSAStartup(MAKEWORD(1, 1), &wsaData);
  167. }
  168.  
  169. void psock_errno(char *text)
  170. {
  171.   int rc = WSAGetLastError();
  172.   printf("%s: error code %d\n", text, rc);
  173. }
  174.  
  175. #ifdef __IBMC__
  176. #define newthread(entry) (_beginthread(entry, 0, THREADSTACK, 0) == -1)
  177. #else
  178. #define newthread(entry) (_beginthread(entry, THREADSTACK, 0) == -1)
  179. #endif
  180. #define THREAD void
  181.  
  182. #endif /* WIN32 */
  183.  
  184. #ifdef UNIX
  185.  
  186. #include <sys/types.h>
  187. #include <sys/socket.h>
  188. #include <sys/time.h>
  189. #include <time.h>
  190. #include <netinet/in.h>
  191. #include <netdb.h>
  192.  
  193. #define psock_errno(x) perror(x)
  194. #define soclose(x) close(x)
  195.  
  196. int sock_init(void)
  197. {
  198.   return 0;
  199. }
  200.  
  201. #include <pthread.h>
  202. pthread_t thread;
  203. #define newthread(entry) (pthread_create(&thread, 0, entry, 0) != 0)
  204. #define THREAD void*
  205.  
  206. #endif /* UNIX */
  207.  
  208. /* global data */
  209.  
  210. #ifndef max
  211. #define max(x, y) ((x) > (y) ? (x) : (y))
  212. #endif
  213.  
  214. #ifndef min
  215. #define min(x, y) ((x) < (y) ? (x) : (y))
  216. #endif
  217.  
  218. #ifndef EINTR
  219. #define EINTR 0
  220. #endif
  221.  
  222. int nSizes[] = {1024, 2048, 4096, 8192, 16384, 32768};
  223. int nnSizes = sizeof(nSizes) / sizeof(int);
  224. #define NMAXSIZE 65536
  225.  
  226. int tSizes[] = {1024, 2048, 4096, 8192, 16384, 32767};
  227. int ntSizes = sizeof(tSizes) / sizeof(int);
  228. #define TMAXSIZE 65536
  229.  
  230. #define INTERVAL 6
  231.  
  232. typedef struct
  233. {
  234.   long cmd;
  235.   long data;
  236. }
  237. CONTROL;
  238.  
  239. #define CMD_QUIT  0
  240. #define CMD_C2S   1
  241. #define CMD_S2C   2
  242. #define CMD_RES   3
  243.  
  244. #define CTLSIZE sizeof(CONTROL)
  245.  
  246. /* timer code */
  247.  
  248. int bTimeOver;
  249.  
  250. #ifdef OS2
  251.  
  252. #define INCL_DOS
  253. #define INCL_NOPM
  254. #include <os2.h>
  255.  
  256. typedef QWORD TIMER;
  257.  
  258. void APIENTRY TimerThread(ULONG nArg)
  259. {
  260.   HEV hSem;
  261.   HTIMER hTimer;
  262.  
  263.   DosCreateEventSem(0, &hSem, DC_SEM_SHARED, 0);
  264.  
  265.   DosAsyncTimer(nArg * 1000, (HSEM) hSem, &hTimer);
  266.   DosWaitEventSem(hSem, SEM_INDEFINITE_WAIT);
  267.   DosStopTimer(hTimer);
  268.  
  269.   DosCloseEventSem(hSem);
  270.  
  271.   bTimeOver = 1;
  272.  
  273.   DosExit(EXIT_THREAD, 0);
  274. }
  275.  
  276. int StartAlarm(long nSeconds)
  277. {
  278.   TID ttid;
  279.  
  280.   bTimeOver = 0;
  281.  
  282.   if (DosCreateThread(&ttid, TimerThread, nSeconds, 0, THREADSTACK))
  283.     return printf("Cannot create timer thread.\n"), -1;
  284.  
  285.   return 0;
  286. }
  287.  
  288. int StartTimer(TIMER *nStart)
  289. {
  290.   if (DosTmrQueryTime(nStart))
  291.     return printf("Timer error.\n"), -1;
  292.  
  293.   return 0;
  294. }
  295.  
  296. long StopTimer(TIMER *nStart, int nAccuracy)
  297. {
  298.   TIMER nStop;
  299.   ULONG nFreq;
  300.  
  301.   if (DosTmrQueryTime(&nStop))
  302.     return printf("Timer error.\n"), -1;
  303.   if (DosTmrQueryFreq(&nFreq))
  304.     return printf("Timer error.\n"), -1;
  305.  
  306.   nFreq = (nFreq + nAccuracy / 2) / nAccuracy;
  307.  
  308.   return (* (long long *) &nStop - * (long long *) nStart) / nFreq;
  309. }
  310.  
  311. #endif /* OS2 */
  312.  
  313. #ifdef WIN32
  314.  
  315. typedef LARGE_INTEGER TIMER;
  316.  
  317. DWORD CALLBACK TimerThread(void * pArg)
  318. {
  319.   Sleep((long) pArg * 1000);
  320.   bTimeOver = 1;
  321.  
  322.   return 0;
  323. }
  324.  
  325. int StartAlarm(long nSeconds)
  326. {
  327.   DWORD ttid;
  328.  
  329.   bTimeOver = 0;
  330.  
  331.   if (CreateThread(0, THREADSTACK, TimerThread, (void *) nSeconds, 0, &ttid) == NULL)
  332.     return printf("Cannot create timer thread.\n"), -1;
  333.  
  334.   return 0;
  335. }
  336.  
  337. int StartTimer(TIMER *nStart)
  338. {
  339.   if (!QueryPerformanceCounter(nStart))
  340.     return printf("Timer error.\n"), -1;
  341.  
  342.   return 0;
  343. }
  344.  
  345. long StopTimer(TIMER *nStart, int nAccuracy)
  346. {
  347.   TIMER nStop, nFreq;
  348.  
  349.   if (!QueryPerformanceCounter(&nStop))
  350.     return printf("Timer error.\n"), -1;
  351.   if (!QueryPerformanceFrequency(&nFreq))
  352.     return printf("Timer error.\n"), -1;
  353.  
  354.   nFreq.QuadPart = (nFreq.QuadPart + nAccuracy / 2) / nAccuracy;
  355.  
  356.   return (nStop.QuadPart - nStart->QuadPart) / nFreq.QuadPart;
  357. }
  358.  
  359. #endif /* WIN32 */
  360.  
  361. #if defined(UNIX) || defined(DJGPP)
  362.  
  363. typedef struct timeval TIMER;
  364.  
  365. void on_alarm(int signum)
  366. {
  367.   alarm(0);
  368.   bTimeOver = 1;
  369. }
  370.  
  371. int StartAlarm(long nSeconds)
  372. {
  373.   bTimeOver = 0;
  374.   signal(SIGALRM, on_alarm);
  375.   alarm(nSeconds);
  376.   return 0;
  377. }
  378.  
  379. int StartTimer(TIMER *nStart)
  380. {
  381.   struct timezone tz = {0, 0};
  382.  
  383.   gettimeofday(nStart, &tz);
  384.  
  385.   return 0;
  386. }
  387.  
  388. long StopTimer(TIMER *nStart, int nAccuracy)
  389. {
  390.   struct timezone tz = {0, 0};
  391.   TIMER nStop;
  392.  
  393.   gettimeofday(&nStop, &tz);
  394.  
  395.   return (nStop.tv_sec - nStart->tv_sec) * nAccuracy
  396.        + (nStop.tv_usec - nStart->tv_usec) * nAccuracy / 1000000;
  397. }
  398.  
  399. #endif /* UNIX || DJGPP */
  400.  
  401. /* initialize data to transfer */
  402.  
  403. char *InitBuffer(int nSize)
  404. {
  405.   char *cBuffer = malloc(nSize);
  406.  
  407.   if (cBuffer != NULL)
  408.   {
  409.     int i;
  410.  
  411.     cBuffer[0] = 0;
  412.     srand(1);
  413.  
  414.     for (i = 1; i < nSize; i++)
  415.       cBuffer[i] = (char) rand();
  416.   }
  417.  
  418.   return cBuffer;
  419. }
  420.  
  421. char *PacketSize(int nSize)
  422. {
  423.   static char szBuffer[64];
  424.  
  425.   if ((nSize % 1024) == 0 || (nSize % 1024) == 1023)
  426.     sprintf(szBuffer, "%2dk", (nSize + 512) / 1024);
  427.   else
  428.     sprintf(szBuffer, "%d", nSize);
  429.  
  430.   return szBuffer;
  431. }
  432.  
  433. /* NetBIOS code */
  434.  
  435. #ifdef USE_NETBIOS
  436.  
  437. char *szServerName = DEFAULTNBSRV;
  438. char *szClientName = DEFAULTNBCLT;
  439. USHORT nAdapter = 0;
  440.  
  441. NCB WorkNcb;
  442. USHORT nLSN, rc;
  443.  
  444. THREAD NetBIOS_Server(void *arg)
  445. {
  446.   char *cBuffer;
  447.   CONTROL ctl;
  448.   int nByte;
  449.  
  450.   if ((cBuffer = InitBuffer(NMAXSIZE)) == NULL)
  451.   {
  452.     perror("malloc()");
  453.     return;
  454.   }
  455.  
  456.   if ((rc = NCBAddName(&WorkNcb, nAdapter, szServerName)) != 0 && rc != 13)
  457.   {
  458.     printf("NetBIOS AddName Failed, rc=0x%02X\n", rc);
  459.     free(cBuffer);
  460.     return;
  461.   }
  462.  
  463.   for (;;)
  464.   {
  465.     printf("NetBIOS server listening.\n");
  466.  
  467.     if ((rc = NCBListen(&WorkNcb, nAdapter, szServerName, "*", 0, 0, TRUE)) != 0)
  468.     {
  469.       printf("NetBIOS Listen failed, rc=0x%02X\n", rc);
  470.       break;
  471.     }
  472.  
  473.     nLSN = WorkNcb.basic_ncb.bncb.ncb_lsn;
  474.  
  475.     printf("NetBIOS connection established ... ");
  476.     fflush(stdout);
  477.  
  478.     for (;;)
  479.     {
  480.       if ((rc = NCBReceive(&WorkNcb, nAdapter, nLSN,
  481.                (void *) &ctl, CTLSIZE, TRUE)) != 0)
  482.       {
  483.     printf("NetBIOS Receive Failed, rc=0x%02X\n", rc);
  484.     break;
  485.       }
  486.  
  487.       if (ctl.cmd == CMD_C2S)
  488.       {
  489.     printf("\nReceiving from client, packet size %s ...", PacketSize(ctl.data));
  490.  
  491.     do
  492.     {
  493.       for (nByte = 0; nByte < ctl.data; )
  494.       {
  495.         rc = NCBReceive(&WorkNcb, nAdapter, nLSN,
  496.                     cBuffer + nByte, ctl.data - nByte, TRUE);
  497.  
  498.         if (rc != 0 && rc != NB_MESSAGE_INCOMPLETE)
  499.         {
  500.           printf("NetBIOS Receive Failed, rc=0x%02X\n", rc);
  501.           break;
  502.         }
  503.  
  504.         nByte += WorkNcb.basic_ncb.bncb.ncb_length;
  505.       }
  506.     }
  507.     while (cBuffer[0] == 0 && rc == 0);
  508.       }
  509.       else if (ctl.cmd == CMD_S2C)
  510.       {
  511.     printf("\nSending to client, packet size %s ...", PacketSize(ctl.data));
  512.  
  513.     if (StartAlarm(INTERVAL) == 0)
  514.     {
  515.       cBuffer[0] = 0;
  516.  
  517.       while (!bTimeOver)
  518.       {
  519.         for (nByte = 0; nByte < ctl.data; )
  520.         {
  521.           if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  522.                 cBuffer + nByte, ctl.data - nByte, TRUE)) != 0)
  523.           {
  524.         printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  525.         break;
  526.           }
  527.  
  528.           nByte += WorkNcb.basic_ncb.bncb.ncb_length;
  529.         }
  530.       }
  531.  
  532.       cBuffer[0] = 1;
  533.  
  534.       if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  535.                 cBuffer, ctl.data, TRUE)) != 0)
  536.       {
  537.         printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  538.         break;
  539.       }
  540.     }
  541.       }
  542.       else /* quit */
  543.     break;
  544.     }
  545.  
  546.     NCBHangup(&WorkNcb, nAdapter, nLSN);
  547.  
  548.     printf("\nDone.\n");
  549.   }
  550.  
  551.   NCBDeleteName(&WorkNcb, nAdapter, szServerName);
  552.  
  553.   free(cBuffer);
  554. }
  555.  
  556. void NetBIOS_Bench(void *arg)
  557. {
  558.   char *cBuffer;
  559.   TIMER nTimer;
  560.   CONTROL ctl;
  561.   long nTime, nResult;
  562.   long nData;
  563.   int i;
  564.   int nByte;
  565.  
  566.   if ((cBuffer = InitBuffer(NMAXSIZE)) == NULL)
  567.   {
  568.     perror("malloc()");
  569.     return;
  570.   }
  571.  
  572.   if ((rc = NCBAddName(&WorkNcb, nAdapter, szClientName)) != 0 && rc != 13)
  573.   {
  574.     printf("NetBIOS AddName Failed, rc=0x%02X\n", rc);
  575.     free(cBuffer);
  576.     return;
  577.   }
  578.  
  579.   if ((rc = NCBCall(&WorkNcb, nAdapter, szClientName, szServerName, 0, 0, TRUE)) != 0)
  580.     printf("NetBIOS Call failed, rc=0x%02X\n", rc);
  581.   else
  582.   {
  583.     nLSN = WorkNcb.basic_ncb.bncb.ncb_lsn;
  584.  
  585.     printf("\nNetBIOS connection established.\n");
  586.  
  587.     for (i = 0; i < nnSizes; i++)
  588.     {
  589.       printf("Packet size %s bytes: ", PacketSize(nSizes[i]));
  590.       fflush(stdout);
  591.  
  592.       /* tell the server we will send it data now */
  593.  
  594.       ctl.cmd = CMD_C2S;
  595.       ctl.data = nSizes[i];
  596.  
  597.       if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  598.             (void *) &ctl, CTLSIZE, TRUE)) != 0)
  599.       {
  600.     printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  601.     break;
  602.       }
  603.  
  604.       /* 1 - Tx test */
  605.  
  606.       if (StartAlarm(INTERVAL) == 0 && StartTimer(&nTimer) == 0)
  607.       {
  608.     nData = 0;
  609.     cBuffer[0] = 0;
  610.  
  611.     while (!bTimeOver)
  612.     {
  613.       for (nByte = 0; nByte < ctl.data; )
  614.       {
  615.         if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  616.                   cBuffer + nByte, ctl.data - nByte, TRUE)) != 0)
  617.         {
  618.           printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  619.           break;
  620.         }
  621.  
  622.         nByte += WorkNcb.basic_ncb.bncb.ncb_length;
  623.       }
  624.  
  625.       nData += ctl.data;
  626.     }
  627.  
  628.     if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  629.       printf("(failed)");
  630.     else
  631.     if (nData < 100 * 1024 * INTERVAL)
  632.     {
  633.       nResult = nData * 1024 / nTime;
  634.       printf(" %ld Byte/s", nResult);
  635.     }
  636.     else
  637.     {
  638.       nResult = nData / nTime;
  639.       printf(" %ld KByte/s", nResult);
  640.     }
  641.  
  642.     printf(" Tx, ");
  643.     fflush(stdout);
  644.  
  645.     cBuffer[0] = 1;
  646.  
  647.     if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  648.               cBuffer, ctl.data, TRUE)) != 0)
  649.     {
  650.       printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  651.       break;
  652.     }
  653.       }
  654.  
  655.       /* tell the server we expect him to send us data now */
  656.  
  657.       ctl.cmd = CMD_S2C;
  658.       ctl.data = nSizes[i];
  659.  
  660.       if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  661.             (void *) &ctl, CTLSIZE, TRUE)) != 0)
  662.       {
  663.     printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  664.     break;
  665.       }
  666.  
  667.       /* 2 - Rx test */
  668.  
  669.       if (StartTimer(&nTimer) == 0)
  670.       {
  671.     nData = 0;
  672.  
  673.     do
  674.     {
  675.       for (nByte = 0; nByte < ctl.data; )
  676.       {
  677.         rc = NCBReceive(&WorkNcb, nAdapter, nLSN,
  678.                     cBuffer + nByte, ctl.data - nByte, TRUE);
  679.  
  680.         if (rc != 0 && rc != NB_MESSAGE_INCOMPLETE)
  681.         {
  682.           printf("NetBIOS Receive Failed, rc=0x%02X\n", rc);
  683.           break;
  684.         }
  685.  
  686.         nByte += WorkNcb.basic_ncb.bncb.ncb_length;
  687.       }
  688.  
  689.       nData += ctl.data;
  690.     }
  691.     while (cBuffer[0] == 0 && rc == 0);
  692.  
  693.     if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  694.       printf(" (failed)");
  695.     else
  696.       if (nData < 100 * 1024 * INTERVAL)
  697.       {
  698.         nResult = nData * 1024 / nTime;
  699.         printf(" %ld Byte/s", nResult);
  700.       }
  701.       else
  702.       {
  703.         nResult = nData / nTime;
  704.         printf(" %ld KByte/s", nResult);
  705.       }
  706.  
  707.     printf(" Rx.\n");
  708.       }
  709.     }
  710.  
  711.     ctl.cmd = CMD_QUIT;
  712.     ctl.data = 0;
  713.  
  714.     if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  715.               (void *) &ctl, CTLSIZE, TRUE)) != 0)
  716.       printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  717.  
  718.     NCBHangup(&WorkNcb, nAdapter, nLSN);
  719.   }
  720.  
  721.   NCBDeleteName(&WorkNcb, nAdapter, szClientName);
  722.  
  723.   free(cBuffer);
  724. }
  725.  
  726. #endif /* USE_NETBIOS */
  727.  
  728. /* TCP/IP code */
  729.  
  730. int _send(int socket, void *buffer, int size, int flags)
  731. {
  732.   int rc = send(socket, buffer, size, flags);
  733.  
  734.   if (rc < 0)
  735.   {
  736.     psock_errno("send()");
  737.     return -1;
  738.   }
  739.  
  740.   if (rc != size)
  741.     return 1;
  742.  
  743.   return 0;
  744. }
  745.  
  746. int _recv(int socket, void *buffer, int size, int flags)
  747. {
  748.   int rc = recv(socket, buffer, size, flags);
  749.  
  750.   if (rc < 0)
  751.   {
  752.     psock_errno("recv()");
  753.     return -1;
  754.   }
  755.  
  756.   if (rc != size)
  757.     return 1;
  758.  
  759.   return 0;
  760. }
  761.  
  762. const int sobufsize = 131072;
  763. int nPort = DEFAULTPORT;
  764. int nAuxPort = DEFAULTPORT + 1;
  765. struct in_addr addr_server;
  766. struct in_addr addr_local;
  767.  
  768. int udpsocket, udpd;
  769. unsigned long nUDPCount;
  770. long long nUDPData;
  771.  
  772. THREAD TCP_Server(void *arg)
  773. {
  774.   char *cBuffer;
  775.   CONTROL ctl;
  776.   long long nData;
  777.   struct sockaddr_in sa_server, sa_client;
  778.   int server, client, length;
  779.   struct timeval tv;
  780.   fd_set fds;
  781.   int rc;
  782.   int nByte;
  783.  
  784.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  785.   {
  786.     perror("malloc()");
  787.     return;
  788.   }
  789.  
  790.   if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  791.   {
  792.     psock_errno("socket()");
  793.     free(cBuffer);
  794.     return;
  795.   }
  796.  
  797.   setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  798.   setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  799.  
  800.   sa_server.sin_family = AF_INET;
  801.   sa_server.sin_port = htons(nPort);
  802.   sa_server.sin_addr = addr_local;
  803.  
  804.   if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  805.   {
  806.     psock_errno("bind()");
  807.     soclose(server);
  808.     free(cBuffer);
  809.     return;
  810.   }
  811.  
  812.   if (listen(server, 2) != 0)
  813.   {
  814.     psock_errno("listen()");
  815.     soclose(server);
  816.     free(cBuffer);
  817.     return;
  818.   }
  819.  
  820.   for (;;)
  821.   {
  822.     printf("TCP server listening.\n");
  823.  
  824.     FD_ZERO(&fds);
  825.     FD_SET(server, &fds);
  826.     tv.tv_sec  = 3600;
  827.     tv.tv_usec = 0;
  828.  
  829.     if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
  830.     {
  831.       psock_errno("select()");
  832.       break;
  833.     }
  834.  
  835.     if (rc == 0 || FD_ISSET(server, &fds) == 0)
  836.       continue;
  837.  
  838.     length = sizeof(sa_client);
  839.     if ((client = accept(server, (struct sockaddr *) &sa_client, &length)) == -1)
  840.       continue;
  841.  
  842.     setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  843.     setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  844.  
  845.     printf("TCP connection established ... ");
  846.     fflush(stdout);
  847.  
  848.     for (;;)
  849.     {
  850.       if (_recv(client, (void *) &ctl, CTLSIZE, 0))
  851.     break;
  852.  
  853.       ctl.cmd = ntohl(ctl.cmd);
  854.       ctl.data = ntohl(ctl.data);
  855.  
  856.       if (ctl.cmd == CMD_C2S)
  857.       {
  858.     printf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data));
  859.     nData = 0;
  860.  
  861.     do
  862.     {
  863.       for (nByte = 0; nByte < ctl.data; )
  864.       {
  865.         rc = recv(client, cBuffer + nByte, ctl.data - nByte, 0);
  866.  
  867.         if (rc < 0 && errno != EINTR)
  868.         {
  869.           psock_errno("recv()");
  870.           break;
  871.         }
  872.         
  873.         if (rc > 0)
  874.           nByte += rc;
  875.       }
  876.  
  877.       nData += ctl.data;
  878.     }
  879.     while (cBuffer[0] == 0 && rc > 0);
  880.       }
  881.       else if (ctl.cmd == CMD_S2C)
  882.       {
  883.     if (StartAlarm(INTERVAL) == 0)
  884.     {
  885.       printf("\nSending to client, packet size %s ... ", PacketSize(ctl.data));
  886.       cBuffer[0] = 0;
  887.       nData = 0;
  888.  
  889.       while (!bTimeOver)
  890.       {
  891.         for (nByte = 0; nByte < ctl.data; )
  892.         {
  893.           rc = send(client, cBuffer + nByte, ctl.data - nByte, 0);
  894.  
  895.           if (rc < 0 && errno != EINTR)
  896.           {
  897.         psock_errno("send()");
  898.         break;
  899.           }
  900.  
  901.           if (rc > 0)
  902.         nByte += rc;
  903.         }
  904.  
  905.         nData += ctl.data;
  906.       }
  907.  
  908.       cBuffer[0] = 1;
  909.  
  910.       if (_send(client, cBuffer, ctl.data, 0))
  911.         break;
  912.     }
  913.       }
  914.       else /* quit */
  915.     break;
  916.     }
  917.  
  918.     printf("\nDone.\n");
  919.  
  920.     soclose(client);
  921.  
  922.     if (rc < 0)
  923.       break;
  924.   }
  925.  
  926.   soclose(server);
  927.  
  928.   free(cBuffer);
  929. }
  930.  
  931. void TCP_Bench(void *arg)
  932. {
  933.   char *cBuffer;
  934.   CONTROL ctl;
  935.   TIMER nTimer;
  936.   long nTime, nResult;
  937.   long long nData;
  938.   int i;
  939.   struct sockaddr_in sa_server;
  940.   int server;
  941.   int rc;
  942.   int nByte;
  943.  
  944.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  945.   {
  946.     perror("malloc()");
  947.     return;
  948.   }
  949.  
  950.   if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  951.   {
  952.     psock_errno("socket()");
  953.     free(cBuffer);
  954.     return;
  955.   }
  956.  
  957.   setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  958.   setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  959.  
  960.   sa_server.sin_family = AF_INET;
  961.   sa_server.sin_port = htons(nPort);
  962.   sa_server.sin_addr = addr_server;
  963.  
  964.   if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  965.   {
  966.     psock_errno("connect()");
  967.     soclose(server);
  968.     free(cBuffer);
  969.     return;
  970.   }
  971.  
  972.   printf("\nTCP connection established.\n");
  973.  
  974.   for (i = 0; i < ntSizes; i++)
  975.   {
  976.     printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
  977.     fflush(stdout);
  978.  
  979.     /* tell the server we will send it data now */
  980.  
  981.     ctl.cmd = htonl(CMD_C2S);
  982.     ctl.data = htonl(tSizes[i]);
  983.  
  984.     if (_send(server, (void *) &ctl, CTLSIZE, 0))
  985.       break;
  986.  
  987.     /* 1 - Tx test */
  988.  
  989.     if (StartAlarm(INTERVAL) == 0 && StartTimer(&nTimer) == 0)
  990.     {
  991.       nData = 0;
  992.       cBuffer[0] = 0;
  993.  
  994.       while (!bTimeOver)
  995.       {
  996.     for (nByte = 0; nByte < tSizes[i]; )
  997.     {
  998.       rc = send(server, cBuffer + nByte, tSizes[i] - nByte, 0);
  999.  
  1000.       if (rc < 0 && errno != EINTR)
  1001.       {
  1002.         psock_errno("send()");
  1003.         break;
  1004.       }
  1005.       
  1006.       if (rc > 0)
  1007.         nByte += rc;
  1008.     }
  1009.  
  1010.     nData += tSizes[i];
  1011.       }
  1012.  
  1013.       if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  1014.     printf(" (failed)");
  1015.  
  1016.       if (nData < 100 * 1024 * INTERVAL)
  1017.       {
  1018.     nResult = nData * 1024 / nTime;
  1019.     printf(" %ld Byte/s", nResult);
  1020.       }
  1021.       else
  1022.       {
  1023.     nResult = nData / nTime;
  1024.     printf(" %ld KByte/s", nResult);
  1025.       }
  1026.  
  1027.       printf(" Tx, ");
  1028.       fflush(stdout);
  1029.  
  1030.       cBuffer[0] = 1;
  1031.  
  1032.       if (_send(server, cBuffer, tSizes[i], 0))
  1033.     break;
  1034.     }
  1035.  
  1036.     /* tell the server we expect him to send us data now */
  1037.  
  1038.     ctl.cmd = htonl(CMD_S2C);
  1039.     ctl.data = htonl(tSizes[i]);
  1040.  
  1041.     if (_send(server, (void *) &ctl, CTLSIZE, 0))
  1042.       break;
  1043.  
  1044.     /* 2 - Rx test */
  1045.  
  1046.     if (StartTimer(&nTimer) == 0)
  1047.     {
  1048.       nData = 0;
  1049.  
  1050.       do
  1051.       {
  1052.     for (nByte = 0; nByte < tSizes[i]; )
  1053.     {
  1054.       rc = recv(server, cBuffer + nByte, tSizes[i] - nByte, 0);
  1055.  
  1056.       if (rc < 0 && errno != EINTR)
  1057.       {
  1058.         psock_errno("recv()");
  1059.         break;
  1060.       }
  1061.       
  1062.       if (rc > 0)
  1063.         nByte += rc;
  1064.     }
  1065.  
  1066.     nData += tSizes[i];
  1067.       }
  1068.       while (cBuffer[0] == 0 && rc > 0);
  1069.  
  1070.       if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  1071.     printf(" (failed)");
  1072.  
  1073.       if (nData < 100 * 1024 * INTERVAL)
  1074.       {
  1075.     nResult = nData * 1024 / nTime;
  1076.     printf(" %ld Byte/s", nResult);
  1077.       }
  1078.       else
  1079.       {
  1080.     nResult = nData / nTime;
  1081.     printf(" %ld KByte/s", nResult);
  1082.       }
  1083.  
  1084.       printf(" Rx.\n");
  1085.     }
  1086.   }
  1087.  
  1088.   ctl.cmd = htonl(CMD_QUIT);
  1089.   ctl.data = 0;
  1090.  
  1091.   _send(server, (void *) &ctl, CTLSIZE, 0);
  1092.  
  1093.   printf("Done.\n");
  1094.  
  1095.   soclose(server);
  1096.  
  1097.   free(cBuffer);
  1098. }
  1099.  
  1100. THREAD UDP_Receiver(void *arg)
  1101. {
  1102.   char *cBuffer;
  1103.   struct sockaddr_in sa_server, sa_client;
  1104.   int rc, nBytes;
  1105.  
  1106.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  1107.   {
  1108.     perror("malloc()");
  1109.     return;
  1110.   }
  1111.  
  1112.   if ((udpsocket = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
  1113.   {
  1114.     psock_errno("socket(DGRAM)");
  1115.     free(cBuffer);
  1116.     return;
  1117.   }
  1118.   
  1119.   setsockopt(udpsocket, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  1120.   setsockopt(udpsocket, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  1121.  
  1122.   sa_server.sin_family = AF_INET;
  1123.   sa_server.sin_port = htons(nAuxPort);
  1124.   sa_server.sin_addr = addr_local;
  1125.  
  1126.   if (bind(udpsocket, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  1127.   {
  1128.     psock_errno("bind(DGRAM)");
  1129.     soclose(udpsocket);
  1130.     free(cBuffer);
  1131.     return;
  1132.   }
  1133.  
  1134.   udpd = 1;
  1135.  
  1136.   for (;;)
  1137.   {
  1138.     nBytes = sizeof(sa_client);
  1139.     rc = recvfrom(udpsocket, cBuffer, TMAXSIZE, 0, (struct sockaddr *) &sa_client, &nBytes);
  1140.  
  1141.     if (rc < 0 && errno != EINTR)
  1142.       psock_errno("recvfrom()");
  1143.  
  1144.     if (rc > 0)
  1145.     {
  1146.       nUDPCount++;
  1147.       nUDPData += rc;
  1148.     }
  1149.   }
  1150.  
  1151.   soclose(udpsocket);
  1152.   free(cBuffer);
  1153. }
  1154.  
  1155. THREAD UDP_Server(void *arg)
  1156. {
  1157.   char *cBuffer;
  1158.   CONTROL ctl;
  1159.   long long nData;
  1160.   struct sockaddr_in sa_server, sa_client;
  1161.   int server, client;
  1162.   struct timeval tv;
  1163.   fd_set fds;
  1164.   int rc, nByte, nLength;
  1165.  
  1166.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  1167.   {
  1168.     perror("malloc()");
  1169.     return;
  1170.   }
  1171.  
  1172.   if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  1173.   {
  1174.     psock_errno("socket(STREAM)");
  1175.     free(cBuffer);
  1176.     return;
  1177.   }
  1178.  
  1179.   setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  1180.   setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  1181.  
  1182.   sa_server.sin_family = AF_INET;
  1183.   sa_server.sin_port = htons(nAuxPort);
  1184.   sa_server.sin_addr = addr_local;
  1185.  
  1186.   if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  1187.   {
  1188.     psock_errno("bind(STREAM)");
  1189.     soclose(server);
  1190.     free(cBuffer);
  1191.     return;
  1192.   }
  1193.  
  1194.   if (listen(server, 2) != 0)
  1195.   {
  1196.     psock_errno("listen()");
  1197.     soclose(server);
  1198.     free(cBuffer);
  1199.     return;
  1200.   }
  1201.  
  1202.   for (;;)
  1203.   {
  1204.     printf("UDP server listening.\n");
  1205.  
  1206.     FD_ZERO(&fds);
  1207.     FD_SET(server, &fds);
  1208.     tv.tv_sec  = 3600;
  1209.     tv.tv_usec = 0;
  1210.  
  1211.     if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
  1212.     {
  1213.       psock_errno("select()");
  1214.       break;
  1215.     }
  1216.  
  1217.     if (rc == 0 || FD_ISSET(server, &fds) == 0)
  1218.       continue;
  1219.  
  1220.     nLength = sizeof(sa_client);
  1221.     if ((client = accept(server, (struct sockaddr *) &sa_client, &nLength)) == -1)
  1222.       continue;
  1223.  
  1224.     setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  1225.     setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  1226.  
  1227.     printf("UDP connection established ... ");
  1228.     fflush(stdout);
  1229.  
  1230.     sa_client.sin_port = htons(nAuxPort);
  1231.  
  1232.     for (;;)
  1233.     {
  1234.       if (_recv(client, (void *) &ctl, CTLSIZE, 0))
  1235.     break;
  1236.  
  1237.       ctl.cmd = ntohl(ctl.cmd);
  1238.       ctl.data = ntohl(ctl.data);
  1239.  
  1240.       if (ctl.cmd == CMD_C2S)
  1241.       {
  1242.     printf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data));
  1243.     nUDPCount = 0;
  1244.     nUDPData = 0;
  1245.  
  1246.     ctl.cmd = htonl(ctl.cmd);
  1247.     ctl.data = htonl(ctl.data);
  1248.  
  1249.     if (_send(client, (void *) &ctl, CTLSIZE, 0))
  1250.       break;
  1251.       }
  1252.       else if (ctl.cmd == CMD_RES)
  1253.       {
  1254.     ctl.cmd = htonl(ctl.cmd);
  1255.     ctl.data = htonl(nUDPCount);
  1256.  
  1257.     if (_send(client, (void *) &ctl, CTLSIZE, 0))
  1258.       break;
  1259.       }
  1260.       else if (ctl.cmd == CMD_S2C)
  1261.       {
  1262.     if (StartAlarm(INTERVAL) == 0)
  1263.     {
  1264.       printf("\nSending to client, packet size %s ... ", PacketSize(ctl.data));
  1265.       cBuffer[0] = 0;
  1266.       nLength = ctl.data;
  1267.  
  1268.       ctl.cmd = htonl(CMD_RES);
  1269.       ctl.data = 0;
  1270.  
  1271.       while (!bTimeOver)
  1272.       {
  1273.         for (nByte = 0; nByte < nLength; )
  1274.         {
  1275.           rc = sendto(udpsocket, cBuffer + nByte, nLength - nByte, 0, 
  1276.               (struct sockaddr *) &sa_client, sizeof(sa_client));
  1277.  
  1278.           if (rc < 0 && errno != EINTR)
  1279.           {
  1280.         psock_errno("sendto()");
  1281.         break;
  1282.           }
  1283.           
  1284.           if (rc > 0)
  1285.         nByte += rc;
  1286.         }
  1287.  
  1288.         ctl.data++;
  1289.       }
  1290.  
  1291.       ctl.data = htonl(ctl.data);
  1292.  
  1293.       if (_send(client, (void *) &ctl, CTLSIZE, 0))
  1294.         break;
  1295.     }
  1296.       }
  1297.       else /* quit */
  1298.     break;
  1299.     }
  1300.  
  1301.     printf("\nDone.\n");
  1302.  
  1303.     soclose(client);
  1304.  
  1305.     if (rc < 0)
  1306.       break;
  1307.   }
  1308.  
  1309.   soclose(server);
  1310.  
  1311.   free(cBuffer);
  1312. }
  1313.  
  1314. void UDP_Bench(void *arg)
  1315. {
  1316.   char *cBuffer;
  1317.   CONTROL ctl;
  1318.   TIMER nTimer;
  1319.   long nTime, nResult, nCount;
  1320.   long long nData;
  1321.   int i;
  1322.   struct sockaddr_in sa_server;
  1323.   int server;
  1324.   int rc, nByte;
  1325.  
  1326.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  1327.   {
  1328.     perror("malloc()");
  1329.     return;
  1330.   }
  1331.  
  1332.   if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  1333.   {
  1334.     psock_errno("socket()");
  1335.     free(cBuffer);
  1336.     return;
  1337.   }
  1338.  
  1339.   setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
  1340.   setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
  1341.  
  1342.   sa_server.sin_family = AF_INET;
  1343.   sa_server.sin_port = htons(nAuxPort);
  1344.   sa_server.sin_addr = addr_server;
  1345.  
  1346.   if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  1347.   {
  1348.     psock_errno("connect()");
  1349.     soclose(server);
  1350.     free(cBuffer);
  1351.     return;
  1352.   }
  1353.  
  1354.   printf("\nUDP connection established.\n");
  1355.  
  1356.   for (i = 0; i < ntSizes; i++)
  1357.   {
  1358.     printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
  1359.     fflush(stdout);
  1360.  
  1361.     /* tell the server we will send it data now */
  1362.  
  1363.     ctl.cmd = htonl(CMD_C2S);
  1364.     ctl.data = htonl(tSizes[i]);
  1365.  
  1366.     if (_send(server, (void *) &ctl, CTLSIZE, 0))
  1367.       break;
  1368.  
  1369.     if (_recv(server, (void *) &ctl, CTLSIZE, 0))
  1370.       break;
  1371.  
  1372.     /* 1 - Tx test */
  1373.  
  1374.     if (StartAlarm(INTERVAL) == 0 && StartTimer(&nTimer) == 0)
  1375.     {
  1376.       cBuffer[0] = 0;
  1377.       nData = 0;
  1378.       nCount = 0;
  1379.  
  1380.       while (!bTimeOver)
  1381.       {
  1382.     for (nByte = 0; nByte < tSizes[i]; )
  1383.     {
  1384.       rc = sendto(udpsocket, cBuffer + nByte, tSizes[i] - nByte, 0, 
  1385.               (struct sockaddr *) &sa_server, sizeof(sa_server));
  1386.  
  1387.       if (rc < 0)
  1388.       {
  1389.         if (errno != EINTR)
  1390.         {
  1391.           psock_errno("sendto()");
  1392.           break;
  1393.         }
  1394.       }
  1395.       else
  1396.         nByte += rc;
  1397.     }
  1398.  
  1399.     nData += tSizes[i];
  1400.     nCount++;
  1401.       }
  1402.       
  1403.       if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  1404.     printf(" (failed)");
  1405.  
  1406.       ctl.cmd = htonl(CMD_RES);
  1407.  
  1408.       if (_send(server, (void *) &ctl, CTLSIZE, 0))
  1409.     break;
  1410.  
  1411.       if (_recv(server, (void *) &ctl, CTLSIZE, 0))
  1412.     break;
  1413.  
  1414.       ctl.data = ntohl(ctl.data);
  1415.       nData = (long long) tSizes[i] * ctl.data;
  1416.  
  1417.       if (nData < 100 * 1024 * INTERVAL)
  1418.       {
  1419.     nResult = nData * 1024 / nTime;
  1420.     printf(" %ld Byte/s", nResult);
  1421.       }
  1422.       else
  1423.       {
  1424.     nResult = nData / nTime;
  1425.     printf(" %ld KByte/s", nResult);
  1426.       }
  1427.  
  1428.       nResult = (nCount - ctl.data) * 100 / nCount;
  1429.       printf(" (%ld%%) Tx, ", nResult);
  1430.       fflush(stdout);
  1431.     }
  1432.  
  1433.     /* tell the server we expect him to send us data now */
  1434.  
  1435.     ctl.cmd = htonl(CMD_S2C);
  1436.     ctl.data = htonl(tSizes[i]);
  1437.     nUDPCount = 0;
  1438.     nUDPData = 0;
  1439.  
  1440.     if (_send(server, (void *) &ctl, CTLSIZE, 0))
  1441.       break;
  1442.  
  1443.     /* 2 - Rx test */
  1444.  
  1445.     if (StartTimer(&nTimer) == 0)
  1446.     {
  1447.       if (_recv(server, (void *) &ctl, CTLSIZE, 0))
  1448.     break;
  1449.  
  1450.       if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  1451.     printf(" (failed)");
  1452.  
  1453.       ctl.data = ntohl(ctl.data);
  1454.       nData = nUDPData;
  1455.  
  1456.       if (nData < 100 * 1024 * INTERVAL)
  1457.       {
  1458.     nResult = nData * 1024 / nTime;
  1459.     printf(" %ld Byte/s", nResult);
  1460.       }
  1461.       else
  1462.       {
  1463.     nResult = nData / nTime;
  1464.     printf(" %ld KByte/s", nResult);
  1465.       }
  1466.  
  1467.       nResult = (ctl.data - nUDPCount) * 100 / ctl.data;
  1468.       printf(" (%ld%%) Rx.\n", nResult);
  1469.     }
  1470.   }
  1471.  
  1472.   ctl.cmd = htonl(CMD_QUIT);
  1473.   ctl.data = 0;
  1474.  
  1475.   _send(server, (void *) &ctl, CTLSIZE, 0);
  1476.  
  1477.   printf("Done.\n");
  1478.  
  1479.   soclose(server);
  1480.  
  1481.   free(cBuffer);
  1482. }
  1483.  
  1484. /* main / user interface */
  1485.  
  1486. int bSRV, bNB, bTCP, bUDP;
  1487.  
  1488. void handler(int sig)
  1489. {
  1490. #ifdef USE_NETBIOS
  1491.   if (bNB)
  1492.   {
  1493.     NCBDeleteName(&WorkNcb, nAdapter, szServerName);
  1494.     NCBDeleteName(&WorkNcb, nAdapter, szClientName);
  1495.     NCBClose(&WorkNcb, nAdapter);
  1496.   }
  1497. #endif
  1498.  
  1499.   exit(0);
  1500. }
  1501.  
  1502. void usage(void)
  1503. {
  1504.   printf(
  1505.      "\nUsage: netio [options] [<server>]\n"
  1506.      "\n  -s            run server side of benchmark (otherwise run client)"
  1507.      "\n  -b <size>[k]  use this block size (otherwise run with 1,2,4,8,16 and 32k)\n"
  1508.  
  1509.      "\n  -t            use TCP protocol for benchmark"
  1510.      "\n  -u            use UDP protocol for benchmark"
  1511.      "\n  -h <addr>     bind TCP and UDP servers to this local host address/name only"
  1512.      "\n                (default is to bind to all local addresses)"
  1513.      "\n  -p <port>     bind TCP and UDP servers to this port (default is %d)\n"
  1514.  
  1515. #ifdef USE_NETBIOS
  1516.      "\n  -n            use NetBIOS protocol for benchmark"
  1517.      "\n  -m <name>     use this as the local NetBIOS name (defaults are NETIOSRV"
  1518.      "\n                for the server and NETIOCLT for the client)"
  1519.      "\n  -a <adapter>  use this NetBIOS adapter (default is 0)\n"
  1520.  
  1521.      "\n  <server>      If TCP or UDP is used for the client, a server name or address"
  1522.      "\n                is required. For NetBIOS, this is optional, for the case that"
  1523.      "\n                the server uses a different NetBIOS name than NETIOSRV.\n"
  1524.  
  1525.      "\nThe server side can run either NetBIOS (-n), TCP (-t) or UDP (-u) protocol"
  1526.      "\nor all three (default, if neither -t, -u or -n are specified). The client"
  1527.      "\nruns one of these protocols only (-t, -u or -n must be specified).\n"
  1528.  
  1529.      "\nThe -m and -a options apply to both client and server sides."
  1530. #else
  1531.          "\n  <server>      If the client side of the benchmark is running,"
  1532.      "\n                a server name or address is required.\n"
  1533.  
  1534.      "\nThe server side can run either TCP (-t) or UDP (-u) protocol or both"
  1535.      "\n(default, if neither -t or -u is specified). The client runs one of"
  1536.      "\nthese protocols only (must specify -t or -u).\n"
  1537. #endif
  1538.      "\n", nPort);
  1539.   exit(1);
  1540. }
  1541.  
  1542. int main(int argc, char **argv)
  1543. {
  1544.   char szVersion[32], *szName = 0, *szLocal = 0, *szEnd;
  1545.   int option;
  1546.   struct hostent *host;
  1547.   long nSize;
  1548.  
  1549.   strcpy(szVersion, rcsrev + sizeof("$Revision: ") - 1);
  1550.   *strchr(szVersion, ' ') = 0;
  1551.  
  1552.   printf("\nNETIO - Network Throughput Benchmark, Version %s"
  1553.      "\n(C) 1997-2003 Kai Uwe Rommel\n", szVersion);
  1554.  
  1555.   if (argc == 1)
  1556.     usage();
  1557.  
  1558.   /* check arguments */
  1559.  
  1560. #ifndef USE_NETBIOS
  1561.   /* bTCP = 1; */
  1562. #endif
  1563.  
  1564.   while ((option = getopt(argc, argv, "?stunp:m:a:dh:b:")) !=  -1)
  1565.     switch (option)
  1566.     {
  1567.     case 's':
  1568.       bSRV = 1;
  1569.       break;
  1570.     case 'b':
  1571.       nSize = strtol(optarg, &szEnd, 10);
  1572.       if (*szEnd == 'k')
  1573.     nSize *= 1024;
  1574.       nSizes[0] = min(max(nSize, 1), NMAXSIZE);
  1575.       tSizes[0] = min(max(nSize, 1), TMAXSIZE);
  1576.       nnSizes = ntSizes = 1;
  1577.       break;
  1578.     case 'p':
  1579.       nPort = atoi(optarg);
  1580.       nAuxPort = nPort + 1;
  1581.       break;
  1582.     case 'h':
  1583.       szLocal = optarg;
  1584.       break;
  1585.     case 't':
  1586.       bTCP = 1;
  1587.       break;
  1588.     case 'u':
  1589.       bUDP = 1;
  1590.       break;
  1591. #ifdef USE_NETBIOS
  1592.     case 'n':
  1593.       bNB = 1;
  1594.       break;
  1595.     case 'a':
  1596.       nAdapter = atoi(optarg);
  1597.       break;
  1598.     case 'm':
  1599.       szName = optarg;
  1600.       break;
  1601. #endif
  1602. #ifdef WATT32
  1603.     case 'd':
  1604.       dbug_init();
  1605.       break;
  1606. #endif
  1607.     default:
  1608.       usage();
  1609.       break;
  1610.     }
  1611.  
  1612.   if (bSRV == 1 && bTCP == 0 && bUDP == 0 && bNB == 0)
  1613.     bTCP = bUDP = bNB = 1;
  1614.  
  1615.   /* initialize NetBIOS and/or TCP/IP */
  1616.  
  1617. #ifdef USE_NETBIOS
  1618.   if (bNB)
  1619.   {
  1620.     NetBIOS_API = NETBIOS;
  1621.  
  1622.     if (NetBIOS_Avail())
  1623.       return printf("NetBIOS not found\n"), 1;
  1624.  
  1625.     if ((rc = NCBReset(&WorkNcb, nAdapter, 2, 2, 2)) != 0)
  1626.       return printf("NetBIOS Reset failed, rc=0x%02X\n", rc), rc;
  1627.  
  1628.     if (szName)
  1629.     {
  1630.       if (bSRV)
  1631.     szServerName = szName;
  1632.       else
  1633.     szClientName = szName;
  1634.     }
  1635.  
  1636.     if (!bSRV & optind < argc)
  1637.       szServerName = argv[optind];
  1638.   }
  1639. #endif
  1640.  
  1641.   if (bTCP || bUDP)
  1642.   {
  1643.     if (sock_init())
  1644.       return psock_errno("sock_init()"), 1;
  1645.  
  1646.     if (szLocal == 0)
  1647.       addr_local.s_addr = INADDR_ANY;
  1648.     else
  1649.     {
  1650.       if (isdigit(*szLocal))
  1651.     addr_local.s_addr = inet_addr(szLocal);
  1652.       else
  1653.       {
  1654.     if ((host = gethostbyname(szLocal)) == NULL)
  1655.       return psock_errno("gethostbyname()"), 1;
  1656.  
  1657.     addr_local = * (struct in_addr *) (host->h_addr);
  1658.       }
  1659.     }
  1660.  
  1661.     if (!bSRV)
  1662.     {
  1663.       if (optind == argc)
  1664.     usage();
  1665.  
  1666.       if (isdigit(*argv[optind]))
  1667.     addr_server.s_addr = inet_addr(argv[optind]);
  1668.       else
  1669.       {
  1670.     if ((host = gethostbyname(argv[optind])) == NULL)
  1671.       return psock_errno("gethostbyname()"), 1;
  1672.  
  1673.     addr_server = * (struct in_addr *) (host->h_addr);
  1674.       }
  1675.     }
  1676.   }
  1677.  
  1678.   /* do work */
  1679.  
  1680.   signal(SIGINT, handler);
  1681.  
  1682.   if (bSRV)
  1683.   {
  1684.     printf("\n");
  1685.  
  1686.     if (bTCP)
  1687.     {
  1688.       if (newthread(TCP_Server))
  1689.     return printf("Cannot create additional thread.\n"), 2;
  1690.     }
  1691.     if (bUDP)
  1692.     {
  1693.       if (newthread(UDP_Receiver))
  1694.     return printf("Cannot create additional thread.\n"), 2;
  1695.       if (newthread(UDP_Server))
  1696.     return printf("Cannot create additional thread.\n"), 2;
  1697.     }
  1698. #ifdef USE_NETBIOS
  1699.     if (bNB)
  1700.     {
  1701.       if (newthread(NetBIOS_Server))
  1702.     return printf("Cannot create additional thread.\n"), 2;
  1703.     }
  1704. #endif
  1705.  
  1706.     while (udpd == 0) sleep(1);
  1707.     for (;;) sleep(86400);
  1708.   }
  1709.   else
  1710.   {
  1711.     if (bTCP + bUDP + bNB > 1) /* exactly one only */
  1712.       usage();
  1713.  
  1714.     if (bTCP)
  1715.       TCP_Bench(0);
  1716.     else if (bUDP)
  1717.     {
  1718.       if (newthread(UDP_Receiver))
  1719.     return printf("Cannot create additional thread.\n"), 2;
  1720.       while (udpd == 0)    sleep(1);
  1721.       UDP_Bench(0);
  1722.     }
  1723. #ifdef USE_NETBIOS
  1724.     else if (bNB)
  1725.       NetBIOS_Bench(0);
  1726. #endif
  1727.   }
  1728.  
  1729.   /* terminate */
  1730.  
  1731. #ifdef USE_NETBIOS
  1732.   if (bNB)
  1733.     NCBClose(&WorkNcb, nAdapter);
  1734. #else
  1735.   printf("\n");
  1736. #endif
  1737.  
  1738.   return 0;
  1739. }
  1740.  
  1741. /* end of netio.c */
  1742.