home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / NMPIPE.ZIP / SERVER.C < prev   
Text File  |  1992-03-07  |  10KB  |  202 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.  
  27. HEV SemHandle;
  28. HFILE FileHandle;
  29. ULONG Instance;
  30. VOID ReadThread(PVOID);
  31.  
  32. main(int argc, char *argv[], char *envp[])
  33. {
  34.   HPIPE PipeHandle;                   /* Pipe Handle value, per instance      */
  35.   ULONG rc,BytesWritten;             /* work values                          */
  36.  
  37.   inforec.Interval=CalibrateTime;     /* initial collection interval, in ms.  */
  38.  
  39.                                       /* create the system semaphore      */
  40.   rc=DosCreateEventSem(SemName,       /* name */
  41.                   &SemHandle,         /* handle on output */
  42.                   DC_SEM_SHARED,      /* MUST be public for sub thread to use it */ 
  43.                   FALSE);             /* System Semaphore name */
  44.  
  45.   _beginthread(ReadThread,NULL,StackSize,NULL); /* start thread */
  46.  
  47.   for( ; ; )                              /* do forever loop */
  48.     {
  49.  
  50.                                  /* make a named pipe or a new instance>first */
  51.     rc=DosCreateNPipe(PipeName,           /* name */
  52.                      &PipeHandle,         /* handle on output */
  53.                      NP_ACCESS_DUPLEX,    /* Duplex pipe, no constant defined */
  54.                                           /* read and write messages */
  55.                                           /* unlimited instance count */
  56.                      NP_WMESG | NP_RMESG | NP_ICOUNT,
  57.                                           /* write message buffer size        */
  58.                                           /* don't forget message length size */
  59.                      Server_WriteSize+PipeMsgHdr,
  60.                                           /* read message buffer size         */
  61.                                           /* don't forget message length size */
  62.                      Server_ReadSize+PipeMsgHdr,
  63.                                          /* client will wait indefinately for */
  64.                                          /* server to issue DosConnectNmPipe  */
  65.  
  66.                      SEM_INDEFINITE_WAIT);
  67.  
  68.                    /* pipe was created, so attach the         */
  69.                    /* semaphore to it                         */
  70.                    /* all handles will have the SAME          */
  71.                    /* semaphore, so we can use QNmSemState    */
  72.                    /* set the unique identifier to the        */
  73.                    /* instance handle so we can use it later  */
  74.                    /* to read/write from/to the client        */
  75.  
  76.     rc=DosSetNPipeSem(PipeHandle,(HSEM)SemHandle,PipeHandle);
  77.  
  78.     DosConnectNPipe(PipeHandle);         /* now wait for client to call      */
  79.  
  80.     Instance++;                       /* client has called, so count instance */
  81.  
  82.                                /* write collection interval to new client now */
  83.     DosWrite(PipeHandle,&inforec.Interval,Server_WriteSize,&BytesWritten);
  84.  
  85.     } /* end for */
  86.  
  87. }
  88.  
  89. /*                                                                            */
  90. /*    This is the main processing thread. It Waits on the System Semaphore    */
  91. /*    then issues the DosQNmPipeSemState to get the status records for ANY    */
  92. /*    instances that may have written data to the server.                     */
  93. /*                                                                            */
  94. /*                                                                            */
  95. /*                                                                            */
  96. /*                                                                            */
  97. /*                                                                            */
  98. VOID ReadThread(PVOID f)
  99. {
  100. PIREC Pirec;                              /* incoming data record pointer */
  101. ULONG Bufsize,Iwork,BytesRead,rc,qrc,BytesWritten; /* work variables */
  102. PPIPESEMSTATE NmPipeData,NpDataEnd,Buffer;       /* status record pointers */
  103. HPIPE PipeHandle;                           /* handle of pipe being processed */
  104. ULONG AdjBaseCount,PostCount;             /* normalized base count            */
  105. #define NpssSize sizeof(PIPESEMSTATE)      /* size of Named Pipe status record */
  106.  
  107.    for(; ; )                              /* forever loop */
  108.      {
  109.                                           /* wait for semaphore to be cleared */
  110.      DosWaitEventSem(SemHandle,SEM_INDEFINITE_WAIT);
  111.  
  112.      DosResetEventSem(SemHandle,&PostCount); /* reset semaphore for next wait    */
  113.  
  114.      while(1)                             /* processing loop */
  115.        {
  116.                 /* allocate a buffer for the status records */
  117.                 /* room for  number of instances + 1        */
  118.                 /* for end of records, record               */
  119.        Bufsize=(Iwork=Instance+1)*NpssSize;
  120.        NmPipeData=Buffer=(PPIPESEMSTATE)malloc(Bufsize);
  121.  
  122.                                           /* get the status records now */
  123.        qrc=DosQueryNPipeSemState((HSEM)SemHandle, NmPipeData, Bufsize);
  124.  
  125.        for( NpDataEnd=NmPipeData+Iwork;   /* loop thru the records */
  126.            NmPipeData<NpDataEnd;          /* while there are some  */
  127.            NmPipeData++)                  /* point to next record  */
  128.          {
  129.                                /* get the key value, which is the pipe handle */
  130.          PipeHandle=(HPIPE)NmPipeData->usKey;
  131.  
  132.          switch(NmPipeData->fStatus)  /* process based on status */
  133.            {
  134.            case NPSS_EOI :                /* no more status records  */
  135.              NmPipeData=NpDataEnd;
  136.              break;
  137.  
  138.            case NPSS_WSPACE:              /* write space is available */
  139.                                          /* since we don't care, we ignore`it */
  140.              break;
  141.  
  142.            case NPSS_RDATA :              /* inbound data from a client */
  143.                                           /* allocate buffer for data   */
  144.                                           /* SHOULD check via DosQNmPipeInfo */
  145.                                        /* but we KNOW how big they SHOULD be */
  146.              Pirec=(PIREC)malloc(Server_ReadSize);
  147.  
  148.                                           /* read a message */
  149.              rc=DosRead(PipeHandle,(PBYTE)Pirec,Server_ReadSize,&BytesRead);
  150.  
  151.                                          /* does client Interval match Server? */
  152.              if(Pirec->Interval!=inforec.Interval)  /* if not, tell client */
  153.                                          /* write new Interval to client   */
  154.                rc=DosWrite(PipeHandle,(PBYTE)&inforec.Interval,Server_WriteSize,&BytesWritten);
  155.  
  156.                                          /* use the data just enough to */
  157.                                          /* report on the client CPU busy state */
  158.              AdjBaseCount=(Pirec->base/Pirec->base_msecs)*Pirec->delta_msec;
  159.              if(AdjBaseCount<Pirec->current)
  160.                Pirec->current=AdjBaseCount;
  161.              printf("Busy=%ld Base=%ld Count=%ld elapsed_ms=%ld Base_ms=%ld\n",
  162.              (ULONG)(((AdjBaseCount-Pirec->current)*100L)/AdjBaseCount),
  163. //           Pirec->base,Pirec->current, Pirec->delta_msec,Pirec->base_msecs);
  164.              AdjBaseCount,Pirec->current, Pirec->delta_msec,Pirec->base_msecs);
  165.  
  166.              free((char *)Pirec);         /* free the receive buffer */
  167.  
  168.              break;
  169.  
  170.            case NPSS_CLOSE :              /* client closed its end of the pipe */
  171.                                           /* close server end as well */
  172.              DosClose((HFILE)NmPipeData->usKey);
  173.  
  174.              Instance--;                  /* reduce active instance count */
  175.  
  176.              break;
  177.  
  178.            default:                       /* should not occur */
  179.                                           /* but we process anyway */
  180.              printf("Unknown Pipe State=%d\n",NmPipeData->fStatus);
  181.  
  182.              break;
  183.  
  184.            } /* end switch */
  185.  
  186.          } /* end for */
  187.  
  188.        free((char *)Buffer);              /* free status record buffer        */
  189.  
  190.               /* there is the possibility that even tho we think we allocated */
  191.               /* enough room for all active client status records, that the   */
  192.               /* write space available records (cause we wrote out an interval*/
  193.               /* record) might not fit in the buffer                          */
  194.               /* in this case we do NOT want to wait on the semaphore again   */
  195.               /* but just go get the records now                              */
  196.        if (qrc==NO_ERROR)
  197.          break;
  198.        }
  199.  
  200.      } /* end forever loop */
  201. }
  202.