home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / NMPIPE.ZIP / CLIENT.C next >
Text File  |  1992-03-07  |  9KB  |  186 lines

  1. #include "nmpipe.h"
  2. /*                                                                            */
  3. /*                                                                            */
  4. /*    Sample Named Pipe Application:                                          */
  5. /*                                                                            */
  6. /*    Server supports MULTIPLE instances of the same pipe                     */
  7. /*    so that multiple clients can call in at any time.                       */
  8. /*                                                                            */
  9. /*    The Server uses the Named Pipe System Semiphore to                      */
  10. /*    manage input stream records.                                            */
  11. /*                                                                            */
  12. /*    The Server writes the each incoming client, the data collection         */
  13. /*    interval upon client callin.                                            */
  14. /*    After that, the client will calibrate itself, and then begin            */
  15. /*    sending records to the server. As the server can change the             */
  16. /*    collection interval dynamically, the server will examine                */
  17. /*    the Interval field of the input record, and if the returned             */
  18. /*    Interval does NOT match the current server setup, the                   */
  19. /*    Server will write, in duplex, the current collection interval           */
  20. /*    to the client for the next cycle.                                       */
  21. /*                                                                            */
  22. /*    Therefore this is a DUPLEX pipe, and the client MUST have a             */
  23. /*    read thread outstanding at all times.                                   */
  24. /*                                                                            */
  25.  
  26. HSEM SemHandle;
  27. HFILE FileHandle;
  28. HPIPE PipeHandle;
  29. BOOL running=TRUE;
  30. BOOL Calibrating=TRUE;
  31. VOID ReadThread(PVOID);
  32. VOID IdleThread(PVOID);
  33.  
  34. main(int argc, char *argv[], char *envp[])
  35. {
  36.  
  37.   char RealPipeName[132]; /* work variables */
  38.   ULONG Action,BytesWritten,BytesRead;
  39.   APIRET rc;
  40. //  struct wksta_info_10 *p;
  41.   BOOL FirstSample=TRUE;                  /* set first sample flag */
  42.  
  43. //NetWkstaGetInfo(Here,10,(PBYTE)NULL,0,&BufSize);  // get size of info
  44. //p=(struct wksta_info_10 *)malloc(BufSize);    // allocate buffer
  45. //NetWkstaGetInfo(Here,10,(PBYTE)p,BufSize,&BufSize);  // get info
  46. //strcpy(inforec.computername,p->wki10_computername); // copy computer name
  47. //free((char *)p);                              // free the buffer
  48.  
  49.  
  50.                             /* as this is the client end of this application */
  51.                             /* the pipe COULD be remote, as such the server  */
  52.                             /* is passed as an argument if it is remote      */
  53.                             /* we have to build the name correctly if we are */
  54.                             /* remote. The name is \\SERVER\PIPE\NAME.EXT    */
  55.   sprintf(RealPipeName,"%s%s%s",
  56.          argc==2?"\\\\":"",
  57.          argc==2?strupr(argv[1]):"",
  58.          PipeName);
  59.  
  60.   printf("Pipe is %s\n", RealPipeName);   /* print derived pipe name */
  61.  
  62.   for(PipeHandle=(HPIPE)NULL; !PipeHandle; )  /* forever loop until pipe open */
  63.     {
  64.                                           /* open the pipe now */
  65.     rc=DosOpen(RealPipeName,&PipeHandle,&Action,0L,FILE_NORMAL,
  66.           OPEN_ACTION_OPEN_IF_EXISTS,OPEN_ACCESS_READWRITE|OPEN_SHARE_DENYNONE,0L);
  67.  
  68.     if(rc==ERROR_PATH_NOT_FOUND)          /* if server not started  */
  69.       DosSleep(WaitForPipe);              /* wait a bit */
  70.     else if(rc==ERROR_PIPE_BUSY)          /* if no free instance */
  71.       rc=DosWaitNPipe(RealPipeName,SEM_INDEFINITE_WAIT); /* wait for one */
  72.     } /* end for */
  73.  
  74.                   /* pipe is open, get the current Interval fromthe server */
  75.   rc=DosRead(PipeHandle,(PBYTE)&inforec.Interval,Client_ReadSize,&BytesRead);
  76.  
  77.   _beginthread(ReadThread,NULL,StackSize,NULL); /* start thread */
  78.  
  79.             /* set this thread to time critical, max.               */
  80.             /* 1. so calibarte/idle thread inherits the same prty   */
  81.             /* 2. When we wake up after the Interval, we DON'T want */
  82.             /* the then idle thread to get any cpu time, that way   */
  83.             /* its counters can't get damaged                       */
  84.  
  85.   DosSetPrty(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
  86.  
  87.   DosSleep(0L);               /* give up our timeslice so we get a clean one */
  88.  
  89.   _beginthread(IdleThread,NULL,StackSize,NULL); /* start it */
  90.  
  91.   DosSleep(CalibrateTime);                /* sleep thru calibrate cycle */
  92.  
  93.   DosEnterCritSec();                      /* don't let idle thread start yet */
  94.  
  95.   Calibrating=FALSE;                      /* turn off the calibrate cycle */
  96.  
  97.   DosExitCritSec();                       /* ok, done with calibrate      */
  98.  
  99.  
  100.   DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&inforec.last_msecs,sizeof(inforec.last_msecs));
  101.  
  102.   while (running)                         /* while we are processing */
  103.     {
  104.  
  105.                                          /* sleep for the requested interval */
  106.                                          /* the idle thread is counting now  */
  107.     DosSleep(inforec.Interval);          /* when it can                      */
  108.  
  109.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&inforec.current_msecs,sizeof(inforec.current_msecs));
  110.  
  111.                               /* calculate idle count since last time        */
  112.     inforec.current = inforec.counter - inforec.last;
  113.  
  114.     inforec.last = inforec.counter;       /* set last tick seen              */
  115.                                           /* milliseconds elased             */
  116.     inforec.delta_msec = inforec.current_msecs - inforec.last_msecs;
  117.                                           /* save last time for next cycle   */
  118.     inforec.last_msecs = inforec.current_msecs;
  119.  
  120.     if (running)                          /* still running ? */
  121.       {
  122.       if(!FirstSample)                    /* ignore the first sample data */
  123.         {
  124.                                           /* send this info to the server    */
  125.         rc=DosWrite(PipeHandle,(PBYTE)&inforec,Client_WriteSize,&BytesWritten);
  126.  
  127.  
  128.         if(rc==ERROR_BROKEN_PIPE)           /* woops, server ended already */
  129.          running=FALSE;                    /* we are done */
  130.         }
  131.       FirstSample=FALSE;                /* set not first sample */
  132.       } /* endif */
  133.     } /* endwhile */
  134.  
  135.   DosEnterCritSec();                      /* no thread switching */
  136.   DosClose(PipeHandle);                   /* close the pipe */
  137.   PipeHandle=(HPIPE)NULL;                 /* clear the handle */
  138.   DosExitCritSec();                       /* thread switching back on */
  139. }
  140.  
  141. VOID ReadThread(PVOID f)
  142. {
  143. ULONG rc,BytesRead;                      /* work variables */
  144.  
  145.    while( PipeHandle )                    /* loop while pipe open */
  146.      {
  147.                                           /* read changed Interval time */
  148.      rc=DosRead(PipeHandle,(PBYTE)&inforec.Interval,Client_ReadSize,&BytesRead);
  149.  
  150.      if(rc==ERROR_BROKEN_PIPE)            /* woops, server went away on us */
  151.        running=FALSE;                     /* lets stop this loop */
  152.      }
  153.  
  154.    DosExit(EXIT_THREAD,0);                /* end this thread now */
  155. }
  156.  
  157. void IdleThread(PVOID f)
  158. {
  159. ULONG CStart_ms;
  160.             /* when this thread gets control it is Time Critical, Max, and */
  161.             /* is expected to calibrate the MAX count possible on this CPU */
  162.             /* this value will be used later to calculate the actual CPU   */
  163.             /* busy values, collected from the second half of this thread   */
  164.  
  165.    DosSleep(0L);        /* give up our timeslice so we get a clean one */
  166.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&CStart_ms,sizeof(CStart_ms));
  167.  
  168.    while(Calibrating)   /* loop while still calibrating */
  169.      inforec.base++;    /* count again */
  170.  
  171.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&inforec.base_msecs,sizeof(inforec.base_msecs));
  172.    inforec.base_msecs -= CStart_ms;        /* elasped milliseconds calibration*/
  173.  
  174.             /* calibration has completed, now lets us play cpu busy counter */
  175.             /* set this thread to lost prty, Idle class, bottom             */
  176.             /* we will get cpu ONLY when there is NOTHING else to do        */
  177.             /* given we know how much NOTHING we did, we can figure out     */
  178.             /* how much something was done                                  */
  179.    DosSetPrty(PRTYS_THREAD,PRTYC_IDLETIME,-31,0);
  180.  
  181.    while (running)                        /* still collecting? */
  182.      inforec.counter++;                   /* count again */
  183.  
  184.    DosExit(EXIT_THREAD,0);                /* end this thread now */
  185.    }
  186.