home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / netio111.zip / netio.c < prev    next >
C/C++ Source or Header  |  2000-03-01  |  16KB  |  812 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.11 2000/03/01 12:21:47 rommel Exp rommel $";
  9. static char *rcsrev = "$Revision: 1.11 $";
  10.  
  11. /*
  12.  * $Log: netio.c,v $
  13.  * Revision 1.11  2000/03/01 12:21:47  rommel
  14.  * fixed _INTEGRAL_MAX_BITS problem for WIN32
  15.  *
  16.  * Revision 1.10  1999/10/28 17:36:57  rommel
  17.  * fixed OS/2 timer code
  18.  *
  19.  * Revision 1.9  1999/10/28 17:04:12  rommel
  20.  * fixed timer code
  21.  *
  22.  * Revision 1.8  1999/10/24 19:08:20  rommel
  23.  * imported DOS support from G. Vanem <giva@bgnett.no>
  24.  *
  25.  *
  26.  * Revision 1.8  1999/10/12 11:02:00  giva
  27.  * added Watt-32 with djgpp support. Added debug mode.
  28.  * G. Vanem <giva@bgnett.no>
  29.  *
  30.  * Revision 1.7  1999/06/13 18:42:25  rommel
  31.  * added Linux port with patches from Detlef Plotzky <plo@bvu.de>
  32.  *
  33.  * Revision 1.6  1998/10/12 11:14:58  rommel
  34.  * change to malloc'ed (and tiled) memory for transfer buffers
  35.  * (hint from Guenter Kukkukk <kukuk@berlin.snafu.de>)
  36.  * for increased performance
  37.  *
  38.  * Revision 1.5  1998/07/31 14:15:03  rommel
  39.  * added random buffer data
  40.  * fixed bugs
  41.  *
  42.  * Revision 1.4  1997/09/12 17:35:04  rommel
  43.  * termination bug fixes
  44.  *
  45.  * Revision 1.3  1997/09/12 12:00:15  rommel
  46.  * added Win32 port
  47.  * (tested for Windows NT only)
  48.  *
  49.  * Revision 1.2  1997/09/12 10:44:22  rommel
  50.  * added TCP/IP and a command line interface
  51.  *
  52.  * Revision 1.1  1996/09/25 08:42:29  rommel
  53.  * Initial revision
  54.  *
  55.  */
  56.  
  57. #ifdef WIN32
  58. #define _INTEGRAL_MAX_BITS 64
  59. #endif
  60.  
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <string.h>
  64. #include <ctype.h>
  65. #include <signal.h>
  66. #if defined(LINUX) || defined(DJGPP)
  67. #include <sys/time.h>
  68. #include <unistd.h>
  69. #include <errno.h>
  70. #else
  71. #include <process.h>
  72. #include "getopt.h"
  73. #include "netbios.h"
  74. #endif
  75.  
  76. /* TCP/IP system specific details */
  77.  
  78. #ifdef OS2
  79. #define BSD_SELECT
  80. #include <types.h>
  81. #include <netinet/in.h>
  82. #include <sys/select.h>
  83. #include <sys/socket.h>
  84. #include <sys/time.h>
  85. #include <netdb.h>
  86. #endif
  87.  
  88. #ifdef WATT32
  89. #include <tcp.h>       /* sock_init() etc. */
  90. #include <netinet/in.h>
  91. #include <sys/socket.h>
  92. #include <netdb.h>
  93. #define soclose     close_s
  94. #define select      select_s
  95. #define psock_errno perror
  96. #endif
  97.  
  98. #ifdef WIN32
  99. #include <windows.h>
  100. #include <winsock.h>
  101. #define soclose closesocket
  102.  
  103. int sock_init(void)
  104. {
  105.   WSADATA wsaData;
  106.   return WSAStartup(MAKEWORD(1, 1), &wsaData);
  107. }
  108.  
  109. void psock_errno(char *text)
  110. {
  111.   int rc = WSAGetLastError();
  112.   printf("%s: error code %d\n", text, rc);
  113. }
  114.  
  115. #endif
  116.  
  117. #ifdef LINUX
  118.  
  119. #include <sys/types.h>
  120. #include <sys/socket.h>
  121. #include <sys/time.h>
  122. #include <netinet/in.h>
  123. #include <netdb.h>
  124.  
  125. #define psock_errno(x) perror(x)
  126. #define soclose(x) close(x)
  127.  
  128. int sock_init(void)
  129. {
  130.   return 0;
  131. }
  132.  
  133. #endif
  134.  
  135. /* global data */
  136.  
  137. #define THREADSTACK 65536
  138.  
  139. int nSizes[] = {1024, 2048, 4096, 8192, 16384, 32768};
  140. #define NSIZES (sizeof(nSizes) / sizeof(int))
  141. #define NMAXSIZE 32768
  142.  
  143. int tSizes[] = {1024, 2048, 4096, 8192, 16384, 32767};
  144. #define TSIZES (sizeof(tSizes) / sizeof(int))
  145. #define TMAXSIZE 32767
  146.  
  147. #define INTERVAL 10
  148.  
  149. /* timer code */
  150.  
  151. int bTimeOver;
  152.  
  153. #ifdef OS2
  154.  
  155. #define INCL_DOS
  156. #define INCL_NOPM
  157. #include <os2.h>
  158.  
  159. typedef QWORD TIMER;
  160.  
  161. void APIENTRY TimerThread(ULONG nArg)
  162. {
  163.   HEV hSem;
  164.   HTIMER hTimer;
  165.  
  166.   DosCreateEventSem(0, &hSem, DC_SEM_SHARED, 0);
  167.  
  168.   DosAsyncTimer(nArg * 1000, (HSEM) hSem, &hTimer);
  169.   DosWaitEventSem(hSem, SEM_INDEFINITE_WAIT);
  170.   DosStopTimer(hTimer);
  171.  
  172.   DosCloseEventSem(hSem);
  173.  
  174.   bTimeOver = 1;
  175.  
  176.   DosExit(EXIT_THREAD, 0);
  177. }
  178.  
  179. int StartAlarm(long nSeconds)
  180. {
  181.   TID ttid;
  182.  
  183.   bTimeOver = 0;
  184.  
  185.   if (DosCreateThread(&ttid, TimerThread, nSeconds, 0, THREADSTACK))
  186.     return printf("Cannot create timer thread.\n"), -1;
  187.  
  188.   return 0;
  189. }
  190.  
  191. int StartTimer(TIMER *nStart)
  192. {
  193.   if (DosTmrQueryTime(nStart))
  194.     return printf("Timer error.\n"), -1;
  195.  
  196.   return 0;
  197. }
  198.  
  199. int StopTimer(TIMER *nStart, int nAccuracy)
  200. {
  201.   TIMER nStop;
  202.   ULONG nFreq;
  203.  
  204.   if (DosTmrQueryTime(&nStop))
  205.     return printf("Timer error.\n"), -1;
  206.   if (DosTmrQueryFreq(&nFreq))
  207.     return printf("Timer error.\n"), -1;
  208.  
  209.   nFreq = (nFreq + nAccuracy / 2) / nAccuracy;
  210.  
  211.   return (* (__int64*) &nStop - * (__int64*) nStart) / nFreq;
  212. }
  213.  
  214. #endif
  215.  
  216. #ifdef WIN32
  217.  
  218. typedef LARGE_INTEGER TIMER;
  219.  
  220. DWORD CALLBACK TimerThread(void * pArg)
  221. {
  222.   Sleep((long) pArg * 1000);
  223.   bTimeOver = 1;
  224.  
  225.   return 0;
  226. }
  227.  
  228. int StartAlarm(long nSeconds)
  229. {
  230.   DWORD ttid;
  231.  
  232.   bTimeOver = 0;
  233.  
  234.   if (CreateThread(0, THREADSTACK, TimerThread, (void *) nSeconds, 0, &ttid) == NULL)
  235.     return printf("Cannot create timer thread.\n"), -1;
  236.  
  237.   return 0;
  238. }
  239.  
  240. int StartTimer(TIMER *nStart)
  241. {
  242.   if (!QueryPerformanceCounter(nStart))
  243.     return printf("Timer error.\n"), -1;
  244.  
  245.   return 0;
  246. }
  247.  
  248. int StopTimer(TIMER *nStart, int nAccuracy)
  249. {
  250.   TIMER nStop, nFreq;
  251.  
  252.   if (!QueryPerformanceCounter(&nStop))
  253.     return printf("Timer error.\n"), -1;
  254.   if (!QueryPerformanceFrequency(&nFreq))
  255.     return printf("Timer error.\n"), -1;
  256.  
  257.   nFreq.QuadPart = (nFreq.QuadPart + nAccuracy / 2) / nAccuracy;
  258.  
  259.   return (nStop.QuadPart - nStart->QuadPart) / nFreq.QuadPart;
  260. }
  261.  
  262. #endif
  263.  
  264. #if defined(LINUX) || defined(DJGPP)
  265.  
  266. typedef struct timeval TIMER;
  267.  
  268. void on_alarm(int signum)
  269. {
  270.   alarm(0);
  271.   bTimeOver = 1;
  272. }
  273.  
  274. int StartAlarm(long nSeconds)
  275. {
  276.   bTimeOver = 0;
  277.   signal(SIGALRM, on_alarm);
  278.   alarm(nSeconds);
  279. }
  280.  
  281. int StartTimer(TIMER *nStart)
  282. {
  283.   struct timezone tz = {0, 0};
  284.  
  285.   gettimeofday(nStart, &tz);
  286.  
  287.   return 0;
  288. }
  289.  
  290. int StopTimer(TIMER *nStart, int nAccuracy)
  291. {
  292.   struct timezone tz = {0, 0};
  293.   TIMER nStop;
  294.  
  295.   gettimeofday(&nStop, &tz);
  296.  
  297.   return (nStop.tv_sec - nStart->tv_sec) * nAccuracy 
  298.        + (nStop.tv_usec - nStart->tv_usec) * nAccuracy / 1000000;
  299. }
  300. #endif /* LINUX || DJGPP */
  301.  
  302. /* initialize data to transfer */
  303.  
  304. char *InitBuffer(int nSize)
  305. {
  306.   char *cBuffer = malloc(nSize);
  307.  
  308.   if (cBuffer != NULL)
  309.   {
  310.     int i;
  311.  
  312.     cBuffer[0] = 0;
  313.     srand(1);
  314.  
  315.     for (i = 1; i < nSize; i++)
  316.       cBuffer[i] = (char) rand();
  317.   }
  318.  
  319.   return cBuffer;
  320. }
  321.  
  322. /* NetBIOS code */
  323.  
  324. #ifdef USE_NETBIOS
  325.  
  326. char *ServerName = "NETIOSRV";
  327. char *ClientName = "NETIOCLT";
  328. USHORT nAdapter = 0;
  329.  
  330. NCB WorkNcb;
  331. USHORT nLSN, rc;
  332.  
  333. void NetBiosServer(void *arg)
  334. {
  335.   char *cBuffer;
  336.   int bQuit = 0;
  337.  
  338.   if ((cBuffer = InitBuffer(NMAXSIZE)) == NULL)
  339.   {
  340.     perror("malloc()");
  341.     return;
  342.   }
  343.  
  344.   if ((rc = NCBAddName(&WorkNcb, nAdapter, ServerName)) != 0 && rc != 13)
  345.   {
  346.     printf("NetBIOS AddName Failed, rc=0x%02X\n", rc);
  347.     free(cBuffer);
  348.     return;
  349.   }
  350.  
  351.   for (;;)
  352.   {
  353.     printf("NetBIOS server Listening.\n");
  354.  
  355.     if ((rc = NCBListen(&WorkNcb, nAdapter, ServerName, "*", 0, 0, TRUE)) != 0)
  356.     {
  357.       printf("NetBIOS Listen failed, rc=0x%02X\n", rc);
  358.       break;
  359.     }
  360.  
  361.     nLSN = WorkNcb.basic_ncb.bncb.ncb_lsn;
  362.  
  363.     printf("NetBIOS connection established ... ");
  364.     fflush(stdout);
  365.  
  366.     while ((rc = NCBReceive(&WorkNcb, nAdapter, nLSN,
  367.                     cBuffer, NMAXSIZE, TRUE)) == 0
  368.        || rc == NB_MESSAGE_INCOMPLETE)
  369.     {
  370.       if (cBuffer[0] == 'B')
  371.       {
  372.       }
  373.     }
  374.  
  375.     if (rc != 0 && rc != NB_SESSION_CLOSED)
  376.       printf("NetBIOS Receive Failed, rc=0x%02X\n", rc);
  377.  
  378.     rc = NCBHangup(&WorkNcb, nAdapter, nLSN);
  379.  
  380.     printf("done.\n");
  381.     fflush(stdout);
  382.  
  383.     if (bQuit)
  384.       break;
  385.   }
  386.  
  387.   NCBDeleteName(&WorkNcb, nAdapter, ServerName);
  388.  
  389.   free(cBuffer);
  390. }
  391.  
  392. void NetBiosBench(void *arg)
  393. {
  394.   char *cBuffer;
  395.   TIMER nTimer;
  396.   long nData, nTime;
  397.   int i;
  398.  
  399.   if ((cBuffer = InitBuffer(NMAXSIZE)) == NULL)
  400.   {
  401.     perror("malloc()");
  402.     return;
  403.   }
  404.  
  405.   if ((rc = NCBAddName(&WorkNcb, nAdapter, ClientName)) != 0 && rc != 13)
  406.   {
  407.     printf("NetBIOS AddName Failed, rc=0x%02X\n", rc);
  408.     free(cBuffer);
  409.     return;
  410.   }
  411.  
  412.   if ((rc = NCBCall(&WorkNcb, nAdapter, ClientName, ServerName, 0, 0, TRUE)) != 0)
  413.     printf("NetBIOS Call failed, rc=0x%02X\n", rc);
  414.   else
  415.   {
  416.     nLSN = WorkNcb.basic_ncb.bncb.ncb_lsn;
  417.  
  418.     printf("\nNetBIOS connection established.\n");
  419.  
  420.     for (i = 0; i < NSIZES; i++)
  421.     {
  422.       printf("%dk packets: ", (nSizes[i] + 512) / 1024);
  423.       fflush(stdout);
  424.  
  425.       nData = 0;
  426.  
  427.       if (StartAlarm(INTERVAL) == 0 && StartTimer(&nTimer) == 0)
  428.       {
  429.     while (!bTimeOver)
  430.     {
  431.       if ((rc = NCBSend(&WorkNcb, nAdapter, nLSN,
  432.                 cBuffer, nSizes[i], TRUE)) != 0)
  433.       {
  434.         printf("NetBIOS Send Failed, rc=0x%02X\n", rc);
  435.         break;
  436.       }
  437.  
  438.       nData += nSizes[i];
  439.     }
  440.  
  441.     if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  442.       printf("Timing failed.\n");
  443.     else
  444.       if (nData < 100 * 1024 * INTERVAL)
  445.         printf("\t%d bytes/sec\n", nData * 1024 / nTime);
  446.       else
  447.         printf("\t%d k/sec\n", nData / nTime);
  448.       }
  449.     }
  450.  
  451.     rc = NCBHangup(&WorkNcb, nAdapter, nLSN);
  452.   }
  453.  
  454.   NCBDeleteName(&WorkNcb, nAdapter, ClientName);
  455.  
  456.   free(cBuffer);
  457. }
  458. #endif /* USE_NETBIOS */
  459.  
  460. /* TCP/IP code */
  461.  
  462. int nPort = 0x494F; /* "IO" */
  463. struct in_addr addr_server;
  464.  
  465. void TcpIpServer(void *arg)
  466. {
  467.   char *cBuffer;
  468.   int bQuit = 0;
  469.   struct sockaddr_in sa_server, sa_client;
  470.   int server, client, length;
  471.   struct timeval tv;
  472.   fd_set fds;
  473.   int rc;
  474.  
  475.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  476.   {
  477.     perror("malloc()");
  478.     return;
  479.   }
  480.  
  481.   if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  482.   {
  483.     psock_errno("socket()");
  484.     free(cBuffer);
  485.     return;
  486.   }
  487.  
  488.   sa_server.sin_family = AF_INET;
  489.   sa_server.sin_port = htons(nPort);
  490.   sa_server.sin_addr.s_addr = INADDR_ANY;
  491.  
  492.   if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  493.   {
  494.     psock_errno("bind()");
  495.     soclose(server);
  496.     free(cBuffer);
  497.     return;
  498.   }
  499.  
  500.   if (listen(server, 2) != 0)
  501.   {
  502.     psock_errno("listen()");
  503.     soclose(server);
  504.     free(cBuffer);
  505.     return;
  506.   }
  507.  
  508.   for (;;)
  509.   {
  510.     printf("TCP/IP server Listening.\n");
  511.  
  512.     FD_ZERO(&fds);
  513.     FD_SET(server, &fds);
  514.     tv.tv_sec  = 3600;
  515.     tv.tv_usec = 0;
  516.  
  517.     if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
  518.     {
  519.       psock_errno("select()");
  520.       break;
  521.     }
  522.  
  523.     if (rc == 0 || FD_ISSET(server, &fds) == 0)
  524.       continue;
  525.  
  526.     length = sizeof(sa_client);
  527.     if ((client = accept(server, (struct sockaddr *) &sa_client, &length)) == -1)
  528.       continue;
  529.  
  530.     printf("TCP/IP connection established ... ");
  531.     fflush(stdout);
  532.  
  533.     while ((rc = recv(client, cBuffer, TMAXSIZE, 0)) > 0);
  534.  
  535.     if (rc == -1)
  536.     {
  537.       psock_errno("recv()");
  538.       bQuit = 1;
  539.     }
  540.     else
  541.       printf("done.\n");
  542.  
  543.     soclose(client);
  544.  
  545.     if (bQuit)
  546.       break;
  547.   }
  548.  
  549.   soclose(server);
  550.  
  551.   free(cBuffer);
  552. }
  553.  
  554. void TcpIpBench(void *arg)
  555. {
  556.   char *cBuffer;
  557.   TIMER nTimer;
  558.   long nData, nTime;
  559.   int i;
  560.   struct sockaddr_in sa_server;
  561.   int server;
  562.   int rc;
  563.  
  564.   if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
  565.   {
  566.     perror("malloc()");
  567.     return;
  568.   }
  569.  
  570.   sa_server.sin_family = AF_INET;
  571.   sa_server.sin_port = htons(nPort);
  572.   sa_server.sin_addr = addr_server;
  573.  
  574.   if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  575.   {
  576.     psock_errno("socket()");
  577.     free(cBuffer);
  578.     return;
  579.   }
  580.  
  581.   if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
  582.   {
  583.     psock_errno("connect()");
  584.     soclose(server);
  585.     free(cBuffer);
  586.     return;
  587.   }
  588.  
  589.   printf("\nTCP/IP connection established.\n");
  590.  
  591.   for (i = 0; i < TSIZES; i++)
  592.   {
  593.     printf("%dk packets: ", (tSizes[i] + 512) / 1024);
  594.     fflush(stdout);
  595.  
  596.     nData = 0;
  597.  
  598.     if (StartAlarm(INTERVAL) == 0 && StartTimer(&nTimer) == 0)
  599.     {
  600.       while (!bTimeOver)
  601.       {
  602.     if ((rc = send(server, cBuffer, tSizes[i], 0)) != tSizes[i] && errno != 0)
  603.     {
  604.       psock_errno("send()");
  605.       break;
  606.     }
  607.  
  608.     nData += tSizes[i];
  609.       }
  610.  
  611.       if ((nTime = StopTimer(&nTimer, 1024)) == -1)
  612.     printf("Timing failed.\n");
  613.       else
  614.     if (nData < 100 * 1024 * INTERVAL)
  615.       printf("\t%d bytes/sec\n", nData * 1024 / nTime);
  616.     else
  617.       printf("\t%d k/sec\n", nData / nTime);
  618.     }
  619.   }
  620.  
  621.   soclose(server);
  622.  
  623.   free(cBuffer);
  624. }
  625.  
  626. /* main / user interface */
  627.  
  628. int bSRV, bNB, bTCP;
  629.  
  630. void handler(int sig)
  631. {
  632. #ifdef USE_NETBIOS
  633.   if (bNB)
  634.   {
  635.     NCBDeleteName(&WorkNcb, nAdapter, ServerName);
  636.     NCBDeleteName(&WorkNcb, nAdapter, ClientName);
  637.     NCBClose(&WorkNcb, nAdapter);
  638.   }
  639. #endif
  640.  
  641.   exit(0);
  642. }
  643.  
  644. void usage(void)
  645. {
  646.   printf(
  647. #ifndef USE_NETBIOS
  648.      "\nUsage: netio [-s] [-p <port>] [<server>]\n"
  649.      "\n\t-s\t\trun server side of benchmark (otherwise run client)"
  650.      "\n\t-p <port>\tuse this port instead of the default (%d)"
  651.          "\n\t<server>\tif the client side of the benchmark is running,"
  652.      "\n\t\t\ta server host name is required\n"
  653. #else
  654.      "\nUsage: netio [-s] [-t | -n] [-p <port>] [-a <adapter>] [<server>]\n"
  655.      "\n\t-s\trun server side of benchmark (otherwise run client)"
  656.      "\n\t-t\tuse TCP/IP protocol for benchmark"
  657.      "\n\t-p <port>\tuse this port for TCP/IP (default is %d)"
  658.      "\n\t-n\tuse NetBIOS protocol for benchmark\n"
  659.      "\n\t-a <adapter>\tuse this NetBIOS adapter (default is 0)\n"
  660.      "\n\t<server>\tif TCP/IP is used for the client,"
  661.      "\n\t\t\ta server host name is required\n"
  662.      "\nThe server side can run either NetBIOS (-n) or TCP/IP (-t) protocol"
  663.      "\nor both (default if neither -t or -n are specified). The client runs"
  664.      "\none of both protocols only (must specify -t or -n).\n"
  665.      "\nThe -p and -a options apply to both client and server sides."
  666. #endif
  667.      "\n", nPort);
  668.   exit(1);
  669. }
  670.  
  671. int main(int argc, char **argv)
  672. {
  673.   char szVersion[32];
  674.   int option;
  675.   struct hostent *host;
  676.  
  677.   strcpy(szVersion, rcsrev + sizeof("$Revision: ") - 1);
  678.   *strchr(szVersion, ' ') = 0;
  679.  
  680.   printf("\nNETIO - Network Throughput Benchmark, Version %s"
  681.      "\n(C) 1997-1999 Kai Uwe Rommel\n", szVersion);
  682.  
  683.   if (argc == 1)
  684.     usage();
  685.  
  686.   /* check arguments */
  687.  
  688. #ifndef USE_NETBIOS
  689.   bTCP = 1;
  690. #endif
  691.  
  692.   while ((option = getopt(argc, argv, "?stnp:a:d")) !=  -1)
  693.     switch (option)
  694.     {
  695.     case 's':
  696.       bSRV = 1;
  697.       break;
  698.     case 't':
  699.       bTCP = 1;
  700.       break;
  701.     case 'p':
  702.       nPort = atoi(optarg);
  703.       break;
  704. #ifdef USE_NETBIOS
  705.     case 'n':
  706.       bNB = 1;
  707.       break;
  708.     case 'a':
  709.       nAdapter = atoi(optarg);
  710.       break;
  711. #endif
  712. #ifdef WATT32
  713.     case 'd':
  714.       dbug_init();
  715.       break;
  716. #endif
  717.     default:
  718.       usage();
  719.       break;
  720.     }
  721.  
  722.   if (bSRV == 1 && bTCP == 0 && bNB == 0)
  723.     bTCP = bNB = 1;
  724.  
  725.   /* initialize NetBIOS and/or TCP/IP */
  726.  
  727. #ifdef USE_NETBIOS
  728.   if (bNB)
  729.   {
  730.     NetBIOS_API = NETBIOS;
  731.  
  732.     if (NetBIOS_Avail())
  733.       return printf("NetBIOS not found\n"), 1;
  734.  
  735.     if ((rc = NCBReset(&WorkNcb, nAdapter, 2, 2, 2)) != 0)
  736.       return printf("NetBIOS Reset failed, rc=0x%02X\n", rc), rc;
  737.   }
  738. #endif
  739.  
  740.   if (bTCP)
  741.   {
  742.     if (sock_init())
  743.       return psock_errno("sock_init()"), 1;
  744.  
  745.     if (!bSRV)
  746.     {
  747.       if (optind == argc)
  748.     usage();
  749.  
  750.       if (isdigit(*argv[optind]))
  751.     addr_server.s_addr = inet_addr(argv[optind]);
  752.       else
  753.       {
  754.     if ((host = gethostbyname(argv[optind])) == NULL)
  755.       return psock_errno("gethostbyname()"), 1;
  756.  
  757.     addr_server = * (struct in_addr *) (host->h_addr);
  758.       }
  759.     }
  760.   }
  761.  
  762.   /* do work */
  763.  
  764.   signal(SIGINT, handler);
  765.  
  766.   if (bSRV)
  767.   {
  768.     printf("\n");
  769.  
  770. #ifndef USE_NETBIOS
  771.     TcpIpServer(0);
  772. #else
  773.     if (bTCP && !bNB)
  774.       TcpIpServer(0);
  775.     else if (bNB && !bTCP)
  776.       NetBiosServer(0);
  777.     else
  778.     {
  779.       if (_beginthread(TcpIpServer, 0, THREADSTACK, 0) == -1)
  780.     return printf("Cannot create additional thread.\n"), 2;
  781.  
  782.       NetBiosServer(0);
  783.     }
  784. #endif
  785.   }
  786.   else
  787.   {
  788.     if ((bTCP ^ bNB) == 0) /* exactly one of both only */
  789.       usage();
  790.  
  791.     if (bTCP)
  792.       TcpIpBench(0);
  793. #ifdef USE_NETBIOS
  794.     else if (bNB)
  795.       NetBiosBench(0);
  796. #endif
  797.   }
  798.  
  799.   /* terminate */
  800.  
  801. #ifdef USE_NETBIOS
  802.   if (bNB)
  803.     NCBClose(&WorkNcb, nAdapter);
  804. #else
  805.   printf("\n");
  806. #endif
  807.  
  808.   return 0;
  809. }
  810.  
  811. /* end of netio.c */
  812.