NMPIPE.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:9k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. #include <stdio.h>
  11. #include <windows.h>
  12. #include <stdlib.h>
  13. #include <process.h>
  14. /* Error checking macro. If bSuccess == TRUE, print error info */
  15. #define PERR(bSuccess, szApi) {if (!(bSuccess)) printf("%s: Error %d from %s 
  16.     on line %dn", __FILE__, GetLastError(), szApi, __LINE__);}
  17. #define DEFNAME "\\.\pipe\nmpipe" /* Default pipe name */
  18. /* Define OVERLAPPED_IO to TRUE to use Overlapped IO. Otherwise define as
  19.    FALSE */
  20. //#define OVERLAPPED_IO TRUE
  21. #define OVERLAPPED_IO FALSE
  22. /* structure to pass into the writer thread */
  23. typedef struct {
  24.   HANDLE hPipe;     /* pipe write handle */
  25.   char *szData;     /* data to repeatedly write */
  26.   int iDataSize;    /* size of buffer pointed to by szData */
  27. } WRITER_PARAMS;
  28. /*
  29.  ** BOOL pipeCheck(HANDLE h)
  30.  *
  31.  *  PARAMETERS: HANDLE hPipe: pipe handle to close if an error condition exists
  32.  *
  33.  *  DESCRIPTION: if GetLastError() returns a common error generated by a
  34.  *               broken pipe, close the pipe handle. Call this right after a
  35.  *               pipe operation.
  36.  *
  37.  *  RETURNS: FALSE if the pipe is broken, TRUE if not.
  38.  *
  39.  */
  40. BOOL pipeCheck(HANDLE hPipe)
  41. {
  42.   DWORD dwLastError = GetLastError();
  43.   if (dwLastError == ERROR_BROKEN_PIPE || dwLastError == ERROR_NO_DATA)
  44.     {
  45.     puts("n* pipe broken, closing...");
  46.     CloseHandle(hPipe);
  47.     return(FALSE);
  48.     }
  49.   if (dwLastError == ERROR_INVALID_HANDLE) /* is handle already closed? */
  50.     return(FALSE);
  51.   return(TRUE);
  52. } /* pipeCheck() */
  53. /*
  54.  ** void reader(HANDLE hPipe)
  55.  *
  56.  *  PARAMETERS: HANDLE hPipe: pipe handle to read from
  57.  *
  58.  *  DESCRIPTION: read from the handle and dump data to the console.
  59.  *
  60.  *  RETURNS: none
  61.  *
  62.  */
  63. void reader(HANDLE hPipe)
  64. {
  65.   char buf[64];
  66.   DWORD dwRead;
  67.   BOOL bSuccess;
  68.   OVERLAPPED ol;
  69.   if (OVERLAPPED_IO) /* if overlapped, prepare OVERLAPPED structure */
  70.   {
  71.     memset(&ol, 0, sizeof(ol));
  72.     ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
  73.     PERR(ol.hEvent, "CreateEvent");
  74.   }
  75.   while (1) 
  76.     {
  77.     bSuccess = ReadFile(hPipe, buf, sizeof(buf), &dwRead,
  78.         OVERLAPPED_IO ? &ol : NULL);
  79.     if (!bSuccess && GetLastError() == ERROR_IO_PENDING)
  80.       bSuccess = GetOverlappedResult(hPipe, &ol, &dwRead, TRUE);
  81.     /* If ReadFile or GetOverlappedResult fails, check pipe. If pipe is
  82.        broken, fall out of loop */
  83.     if (!bSuccess && !pipeCheck(hPipe))
  84.       break;
  85.     /* else check for any other kinds of errors that may have occurred */
  86.     PERR(bSuccess, "ReadFile");
  87.     printf("%.*s", dwRead, buf); /* print only number of chars read */
  88.     } /* while */
  89.   CloseHandle(ol.hEvent);
  90.   _endthread();
  91. } /* reader() */
  92. /*
  93.  ** void writer(WRITER_PARAMS *writer_params)
  94.  *
  95.  *  PARAMETERS: WRITER_PARAMS *writer_params: misc info needed for writing to
  96.  *              the pipe
  97.  *
  98.  *  DESCRIPTION: write data from WRITER_PARAMS to the pipe
  99.  *
  100.  *  RETURNS: none
  101.  *
  102.  */
  103. void writer(WRITER_PARAMS *writer_params)
  104. {
  105.   DWORD dwWritten;
  106.   BOOL bSuccess;
  107.   OVERLAPPED ol;
  108.   if (OVERLAPPED_IO)
  109.   {
  110.     memset(&ol, 0, sizeof(ol));
  111.     ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
  112.     PERR(ol.hEvent, "CreateEvent");
  113.   }
  114.   while(1) 
  115.   {
  116.     bSuccess = WriteFile(writer_params->hPipe, writer_params->szData,
  117.         writer_params->iDataSize, &dwWritten, OVERLAPPED_IO ? &ol : NULL);
  118.     if (!bSuccess && GetLastError() == ERROR_IO_PENDING)
  119.       bSuccess = GetOverlappedResult(writer_params->hPipe, &ol, &dwWritten,
  120.           TRUE);
  121.     /* If ReadFile or GetOverlappedResult fails, check pipe. If pipe is
  122.        broken, fall out of loop */
  123.     if (!bSuccess && !pipeCheck(writer_params->hPipe))
  124.       break;
  125.     /* else check for any other kinds of errors that may have occurred */
  126.     PERR(bSuccess, "WriteFile");
  127.     } /* while */
  128.   free(writer_params);
  129.   CloseHandle(ol.hEvent);
  130.   _endthread();
  131. } /* writer() */
  132. /*
  133.  ** main()
  134.  *
  135.  *  DESCRIPTION: Connect pipe instances to clients. Start a reader thread for
  136.  *               each client. If OVERLAPPED_IO is defined, also start a
  137.  *               writer thread for full duplex pipe I/O testing. If this is
  138.  *               a client, connect to the server pipe and start a writer
  139.  *               thread. If OVERLAPPED_IO, also start a reader thread.
  140.  *
  141.  */
  142. void main(int argc, char *argv[])
  143. {
  144.   HANDLE hPipe;
  145.   BOOL bSuccess;
  146.   BOOL bNotConnected;
  147.   char *szPname;
  148.   WRITER_PARAMS *writer_params;
  149.   DWORD dwClients;
  150.   SECURITY_ATTRIBUTES saPipe;
  151.   OVERLAPPED ol;
  152.   DWORD dwRead;
  153.   if (argc < 3)
  154.     {
  155.     puts("nmpipe [/s|/c] <string> <pipename>");
  156.     puts("'/s' to start as server, '/c' to start as client");
  157.     puts("<string>: string to write to the pipe");
  158.     puts("<pipename>: full UNC name of pipe (optional)");
  159.     puts("example: nmpipe /s "hello from server " \\.\pipe\pipetst");
  160.     return;
  161.     }
  162.   szPname = (argc > 3) ? argv[3] : DEFNAME;
  163.   if (tolower(argv[1][1]) == 's')
  164.     {
  165.     if (OVERLAPPED_IO)
  166.     {
  167.       memset(&ol, 0, sizeof(ol));
  168.       ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
  169.       PERR(ol.hEvent, "CreateEvent");
  170.     }
  171.     SetConsoleTitle("SERVER: nmpipe sample");
  172.     /* set up a NULL DACL in our pipe security descriptor to allow anyone to
  173.        connect to the pipe server */
  174.     saPipe.lpSecurityDescriptor =
  175.         (PSECURITY_DESCRIPTOR) malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
  176.     InitializeSecurityDescriptor(saPipe.lpSecurityDescriptor,
  177.         SECURITY_DESCRIPTOR_REVISION);
  178.     SetSecurityDescriptorDacl(saPipe.lpSecurityDescriptor, TRUE, (PACL) NULL,
  179.         FALSE);
  180.     saPipe.nLength = sizeof(saPipe);
  181.     saPipe.bInheritHandle = TRUE;
  182.     while(1)
  183.       {
  184.       /* Create a named pipe: duplex, type byte, readmode byte, unlimited
  185.          instances, default timeout of 60s */
  186.       hPipe = CreateNamedPipe(szPname, PIPE_ACCESS_DUPLEX |
  187.           (OVERLAPPED_IO ? FILE_FLAG_OVERLAPPED : 0), PIPE_TYPE_BYTE |
  188.           PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0,
  189.           60000, &saPipe);
  190.       PERR(hPipe != INVALID_HANDLE_VALUE, "CreateNamedPipe");
  191.       puts("n* pipe created, waiting for connection...");
  192.       bSuccess = ConnectNamedPipe(hPipe, OVERLAPPED_IO ? &ol : NULL);
  193.       if (!bSuccess && GetLastError() == ERROR_IO_PENDING)
  194.         bSuccess = GetOverlappedResult(hPipe, &ol, &dwRead, TRUE);
  195.       /* check return from either ConnectNamedPipe or GetOverlappedResult.
  196.          If a client managed to connect between the CreateNamedPipe and
  197.          ConnectNamedPipe calls, ERROR_PIPE_CONNECTED will result */
  198.       if (!bSuccess && GetLastError() != ERROR_PIPE_CONNECTED)
  199.         {
  200.         /* something went wrong, report error, close instance and try again */
  201.         PERR(bSuccess, "ConnectNamedPipe");
  202.         CloseHandle(hPipe);
  203.         continue;
  204.         }
  205.       /* find out how many pipe instances there currently are */
  206.       bSuccess = GetNamedPipeHandleState(hPipe, NULL, &dwClients, NULL, NULL,
  207.           NULL, 0);
  208.       PERR(bSuccess, "GetNamedPipeHandleState"); 
  209.       printf("n* %d clients connected", dwClients);
  210.       _beginthread(reader, 0, hPipe);
  211.       writer_params = malloc(sizeof(WRITER_PARAMS));
  212.       writer_params->hPipe = hPipe;
  213.       writer_params->szData = argv[2];
  214.       writer_params->iDataSize = strlen(argv[2]);
  215.       /* WARNING! reading and writing at the same time to a non-overlapped
  216.          pipe is a no-no! If not overlapped, server only reads and client
  217.          only writes */
  218.       if (OVERLAPPED_IO)
  219.         _beginthread(writer, 0, writer_params);
  220.       } /* while */
  221.     CloseHandle(ol.hEvent);
  222.     CloseHandle(hPipe);
  223.     }
  224.   else /* no '/s', assume it's a client */
  225.     {
  226.     char szTemp[64];
  227.     sprintf(szTemp, "Client %s", argv[2]);
  228.     SetConsoleTitle(szTemp);
  229.     bNotConnected = TRUE;
  230.     while (bNotConnected)
  231.       {
  232.       /* attempt to connect to pipe instance */
  233.       hPipe = CreateFile(szPname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  234.           OPEN_EXISTING, OVERLAPPED_IO ? FILE_FLAG_OVERLAPPED : 0, NULL);
  235.       if (GetLastError() == ERROR_PIPE_BUSY)
  236.         {
  237.         puts("Pipe busy, waiting for a pipe instance...");
  238.         bSuccess = WaitNamedPipe(szPname, NMPWAIT_USE_DEFAULT_WAIT);
  239.         PERR(bSuccess, "WaitNamedPipe");
  240.         }
  241.       else
  242.         {
  243.         PERR(hPipe != INVALID_HANDLE_VALUE, "CreateFile");
  244.         bNotConnected = (hPipe == INVALID_HANDLE_VALUE);
  245.         }
  246.       } /* while */
  247.     puts("Connected to pipe...");
  248.     if (OVERLAPPED_IO) /* if overlapped, start reader thread */
  249.       _beginthread(reader, 0, hPipe);
  250.     writer_params = malloc(sizeof(WRITER_PARAMS));
  251.     writer_params->hPipe = hPipe;
  252.     writer_params->szData = argv[2];
  253.     writer_params->iDataSize = strlen(argv[2]);
  254.     writer(writer_params);
  255.     } /* else */
  256.   free(saPipe.lpSecurityDescriptor);
  257.   CloseHandle(hPipe);
  258.   CloseHandle(ol.hEvent);
  259.   return;
  260. }