程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 命名管道 IPC

C++ 命名管道 IPC

編輯:C++入門知識

技術:IPC,RPC,Windows General
主題:Named Pipe,Inter-process Communication
概要:
命名管道是一種進程間單工或雙工的通信機制。它可以在管道服務器和一個或多個管道客戶端間進行。客戶端可以位於本機或互聯網上的遠程計算機。
PIPE_ACCESS_INBOUND(呼入):
Client (GENERIC_WRITE) ---> Server (GENERIC_READ)
PIPE_ACCESS_OUTBOUND(外傳):
Client (GENERIC_READ) <--- Server (GENERIC_WRITE)
PIPE_ACCESS_DUPLEX(雙工):
Client (GENERIC_READ or GENERIC_WRITE, or both) <-->
Server (GENERIC_READ and GENERIC_WRITE)
GENERIC_READ(普通讀)
GENERIC_WRITE(普通寫)
下面的代碼示例演示了如何調用CreateNamedPipe來創建一個名稱為"\\.\pipe\SamplePipe", 的管道。支持全雙工連接。這樣客戶端和服務端都可以從管道中讀寫數據。自定義安全選項使得認證的用戶才具有對管道的讀寫權限。當有客戶端連接管道時,服務端嘗試調用ReadFile從管道中讀出客戶端的消息,並通過調用WriteFile寫入響應消息。
如何演示:
1.在VS2008中編譯CppNamedPipeClient 和CppNamedPipeServer 兩個工程,如果成功你會獲得兩個可執行文件CppNamedPipeClient.exe 和 CppNamedPipeServer.exe.
2.運行CppNamedPipeServer.exe。如果管道創建成功,程序會以命令行形式輸出以下信息:
Server:
 The named pipe (\\.\pipe\SamplePipe) is created.
 Waiting for the client's connection...
3.運行CppNamedPipeClient.exe。如果客戶端成功連接到命名管道會輸出下列信息:
Client:
 The named pipe (\\.\pipe\SamplePipe) is connected.
 同時服務器端會輸出下面的消息來指示有一個客戶端連接到管道
 Server:
 Client is connected.
 4.接下來客戶端會嘗試寫入消息到命名管道,程序輸出:
 Client:
 Send 56 bytes to server: "Default request from client"
 當服務端從客戶端讀取消息後打印出:
 Server:
 Receive 56 bytes from client: "Default request from client"
 接下來,服務端寫入一個回應消息到管道。
 Server:
 Send 58 bytes to client: "Default response from server"
 然後客戶端收到回應消息輸出:
 Client:
 Receive 58 bytes from server: "Default response from server"
 最後斷開連接,關閉管道。
 主要代碼邏輯:
 1.調用CreateNamedPipe創建一個命名管道,指明管道的名稱,方向,傳輸模式,安全屬性等
 [cpp]  // Create the named pipe.  
   hNamedPipe = CreateNamedPipe( 
       FULL_PIPE_NAME,             // Pipe name.  
       PIPE_ACCESS_DUPLEX,         // The pipe is duplex; both server and   
                                   // client processes can read from and   
                                   // write to the pipe  
       PIPE_TYPE_MESSAGE |         // Message type pipe   
       PIPE_READMODE_MESSAGE |     // Message-read mode   
       PIPE_WAIT,                  // Blocking mode is enabled  
       PIPE_UNLIMITED_INSTANCES,   // Max. instances  
       BUFFER_SIZE,                // Output buffer size in bytes  
       BUFFER_SIZE,                // Input buffer size in bytes  
       NMPWAIT_USE_DEFAULT_WAIT,   // Time-out interval  
       pSa                         // Security attributes  
       ); 

// Create the named pipe.
   hNamedPipe = CreateNamedPipe(
       FULL_PIPE_NAME,             // Pipe name.
       PIPE_ACCESS_DUPLEX,         // The pipe is duplex; both server and
                                   // client processes can read from and
                                   // write to the pipe
       PIPE_TYPE_MESSAGE |         // Message type pipe
       PIPE_READMODE_MESSAGE |     // Message-read mode
       PIPE_WAIT,                  // Blocking mode is enabled
       PIPE_UNLIMITED_INSTANCES,   // Max. instances
       BUFFER_SIZE,                // Output buffer size in bytes
       BUFFER_SIZE,                // Input buffer size in bytes
       NMPWAIT_USE_DEFAULT_WAIT,   // Time-out interval
       pSa                         // Security attributes
       );


在這個事例中管道支持全雙工通信。安全屬性允許認證用戶具有讀寫管道權限,所有管理員組成員具有對管道的全部權限


[cpp]  /  
   //   FUNCTION: CreatePipeSecurity(PSECURITY_ATTRIBUTES *)  
   //  
   //   PURPOSE: The CreatePipeSecurity function creates and initializes a new   
   //   SECURITY_ATTRIBUTES structure to allow Authenticated Users read and   
   //   write access to a pipe, and to allow the Administrators group full   
   //   access to the pipe.  
   //  
   //   PARAMETERS:  
   //   * ppSa - output a pointer to a SECURITY_ATTRIBUTES structure that allows   
   //     Authenticated Users read and write access to a pipe, and allows the   
   //     Administrators group full access to the pipe. The structure must be   
   //     freed by calling FreePipeSecurity.  
   //  
   //   RETURN VALUE: Returns TRUE if the function succeeds..  
   //  
   //   EXAMPLE CALL:  
   //  
   //     PSECURITY_ATTRIBUTES pSa = NULL;  
   //     if (CreatePipeSecurity(&pSa))  
   //     {  
   //         // Use the security attributes  
   //         // ...  
   //  
   //         FreePipeSecurity(pSa);  
   //     }  
   //  
   BOOL CreatePipeSecurity(PSECURITY_ATTRIBUTES *ppSa) 

//
   //   FUNCTION: CreatePipeSecurity(PSECURITY_ATTRIBUTES *)
   //
   //   PURPOSE: The CreatePipeSecurity function creates and initializes a new
   //   SECURITY_ATTRIBUTES structure to allow Authenticated Users read and
   //   write access to a pipe, and to allow the Administrators group full
   //   access to the pipe.
   //
   //   PARAMETERS:
   //   * ppSa - output a pointer to a SECURITY_ATTRIBUTES structure that allows
   //     Authenticated Users read and write access to a pipe, and allows the
   //     Administrators group full access to the pipe. The structure must be
   //     freed by calling FreePipeSecurity.
   //
   //   RETURN VALUE: Returns TRUE if the function succeeds..
   //
   //   EXAMPLE CALL:
   //
   //     PSECURITY_ATTRIBUTES pSa = NULL;
   //     if (CreatePipeSecurity(&pSa))
   //     {
   //         // Use the security attributes
   //         // ...
   //
   //         FreePipeSecurity(pSa);
   //     }
   //
   BOOL CreatePipeSecurity(PSECURITY_ATTRIBUTES *ppSa) 2.調用ConnectNamedPipe來等待客戶端連接


[cpp]  if (!ConnectNamedPipe(hNamedPipe, NULL)) 
  { 
      if (ERROR_PIPE_CONNECTED != GetLastError()) 
      { 
          dwError = GetLastError(); 
          wprintf(L"ConnectNamedPipe failed w/err 0x%08lx\n", dwError); 
          goto Cleanup; 
      } 
  } 

 if (!ConnectNamedPipe(hNamedPipe, NULL))
   {
       if (ERROR_PIPE_CONNECTED != GetLastError())
       {
           dwError = GetLastError();
           wprintf(L"ConnectNamedPipe failed w/err 0x%08lx\n", dwError);
           goto Cleanup;
       }
   }
3.通過調用ReadFile和WriteFile從管道中讀出客戶端請求並寫入響應數據[cpp] view plaincopyprint?//   
   // Receive a request from client.  
   //   
 
   BOOL fFinishRead = FALSE; 
   do 
   { 
       wchar_t chRequest[BUFFER_SIZE]; 
       DWORD cbRequest, cbRead; 
       cbRequest = sizeof(chRequest); 
 
       fFinishRead = ReadFile( 
           hNamedPipe,     // Handle of the pipe  
           chRequest,      // Buffer to receive data  
           cbRequest,      // Size of buffer in bytes  
           &cbRead,        // Number of bytes read  
           NULL            // Not overlapped I/O  
           ); 
 
       if (!fFinishRead && ERROR_MORE_DATA != GetLastError()) 
       { 
           dwError = GetLastError(); 
           wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError); 
           goto Cleanup; 
       } 
 
       wprintf(L"Receive %ld bytes from client: \"%s\"\n", cbRead, chRequest); 
 
   } while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA  
 
   //   
   // Send a response from server to client.  
   //   
 
   wchar_t chResponse[] = RESPONSE_MESSAGE; 
   DWORD cbResponse, cbWritten; 
   cbResponse = sizeof(chResponse); 
 
   if (!WriteFile( 
       hNamedPipe,     // Handle of the pipe  
       chResponse,     // Buffer to write  
       cbResponse,     // Number of bytes to write   
       &cbWritten,     // Number of bytes written   
       NULL            // Not overlapped I/O  
       )) 
   { 
       dwError = GetLastError(); 
       wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwError); 
       goto Cleanup; 
   } 
 
   wprintf(L"Send %ld bytes to client: \"%s\"\n", cbWritten, chResponse); 

//
   // Receive a request from client.
   //

   BOOL fFinishRead = FALSE;
   do
   {
       wchar_t chRequest[BUFFER_SIZE];
       DWORD cbRequest, cbRead;
       cbRequest = sizeof(chRequest);

       fFinishRead = ReadFile(
           hNamedPipe,     // Handle of the pipe
           chRequest,      // Buffer to receive data
           cbRequest,      // Size of buffer in bytes
           &cbRead,        // Number of bytes read
           NULL            // Not overlapped I/O
           );

       if (!fFinishRead && ERROR_MORE_DATA != GetLastError())
       {
           dwError = GetLastError();
           wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError);
           goto Cleanup;
       }

       wprintf(L"Receive %ld bytes from client: \"%s\"\n", cbRead, chRequest);

   } while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA

   //
   // Send a response from server to client.
   //

   wchar_t chResponse[] = RESPONSE_MESSAGE;
   DWORD cbResponse, cbWritten;
   cbResponse = sizeof(chResponse);

   if (!WriteFile(
       hNamedPipe,     // Handle of the pipe
       chResponse,     // Buffer to write
       cbResponse,     // Number of bytes to write
       &cbWritten,     // Number of bytes written
       NULL            // Not overlapped I/O
       ))
   {
       dwError = GetLastError();
       wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwError);
       goto Cleanup;
   }

   wprintf(L"Send %ld bytes to client: \"%s\"\n", cbWritten, chResponse);
4.調用FlushFileBuffers在斷開連接之前允許客戶端讀取管道內容。然後斷開客戶端連接


[cpp] FlushFileBuffers(hNamedPipe); 
DisconnectNamedPipe(hNamedPipe); 

FlushFileBuffers(hNamedPipe);
DisconnectNamedPipe(hNamedPipe);
 5.關閉管道


[cpp]  CloseHandle(hNamedPipe); 

CloseHandle(hNamedPipe);
完整代碼:

CppNamedPipeServer.cpp


[cpp] #pragma region Includes  
#include <stdio.h>  
#include <windows.h>  
#include <sddl.h>  
#pragma endregion  
 
 
// The full name of the pipe in the format of \\servername\pipe\pipename.  
#define SERVER_NAME         L"."  
#define PIPE_NAME           L"SamplePipe"  
#define FULL_PIPE_NAME      L"\\\\" SERVER_NAME L"\\pipe\\" PIPE_NAME  
 
#define BUFFER_SIZE     1024  
 
// Response message from client to server. '\0' is appended in the end   
// because the client may be a native C++ application that expects NULL   
// termiated string.  
#define RESPONSE_MESSAGE    L"Default response from server"  
 
 
BOOL CreatePipeSecurity(PSECURITY_ATTRIBUTES *); 
void FreePipeSecurity(PSECURITY_ATTRIBUTES); 
 
 
int wmain(int argc, wchar_t* argv[]) 

    DWORD dwError = ERROR_SUCCESS; 
    PSECURITY_ATTRIBUTES pSa = NULL; 
    HANDLE hNamedPipe = INVALID_HANDLE_VALUE; 
 
    // Prepare the security attributes (the lpSecurityAttributes parameter in   
    // CreateNamedPipe) for the pipe. This is optional. If the   
    // lpSecurityAttributes parameter of CreateNamedPipe is NULL, the named   
    // pipe gets a default security descriptor and the handle cannot be   
    // inherited. The ACLs in the default security descriptor of a pipe grant   
    // full control to the LocalSystem account, (elevated) administrators,   
    // and the creator owner. They also give only read access to members of   
    // the Everyone group and the anonymous account. However, if you want to   
    // customize the security permission of the pipe, (e.g. to allow   
    // Authenticated Users to read from and write to the pipe), you need to   
    // create a SECURITY_ATTRIBUTES structure.  
    if (!CreatePipeSecurity(&pSa)) 
    { 
        dwError = GetLastError(); 
        wprintf(L"CreatePipeSecurity failed w/err 0x%08lx\n", dwError); 
        goto Cleanup; 
    } 
 
    // Create the named pipe.  
    hNamedPipe = CreateNamedPipe( 
        FULL_PIPE_NAME,             // Pipe name.  
        PIPE_ACCESS_DUPLEX,         // The pipe is duplex; both server and   
                                    // client processes can read from and   
                                    // write to the pipe  
        PIPE_TYPE_MESSAGE |         // Message type pipe   
        PIPE_READMODE_MESSAGE |     // Message-read mode   
        PIPE_WAIT,                  // Blocking mode is enabled  
        PIPE_UNLIMITED_INSTANCES,   // Max. instances  
        BUFFER_SIZE,                // Output buffer size in bytes  
        BUFFER_SIZE,                // Input buffer size in bytes  
        NMPWAIT_USE_DEFAULT_WAIT,   // Time-out interval  
        pSa                         // Security attributes  
        ); 
 
    if (hNamedPipe == INVALID_HANDLE_VALUE) 
    { 
        dwError = GetLastError(); 
        wprintf(L"Unable to create named pipe w/err 0x%08lx\n", dwError); 
        goto Cleanup; 
    } 
 
    wprintf(L"The named pipe (%s) is created.\n", FULL_PIPE_NAME); 
 
    // Wait for the client to connect.  
    wprintf(L"Waiting for the client's connection...\n"); 
    if (!ConnectNamedPipe(hNamedPipe, NULL)) 
    { 
        if (ERROR_PIPE_CONNECTED != GetLastError()) 
        { 
            dwError = GetLastError(); 
            wprintf(L"ConnectNamedPipe failed w/err 0x%08lx\n", dwError); 
            goto Cleanup; 
        } 
    } 
    wprintf(L"Client is connected.\n"); 
 
    //   
    // Receive a request from client.  
    //   
 
    BOOL fFinishRead = FALSE; 
    do 
    { 
        wchar_t chRequest[BUFFER_SIZE]; 
        DWORD cbRequest, cbRead; 
        cbRequest = sizeof(chRequest); 
 
        fFinishRead = ReadFile( 
            hNamedPipe,     // Handle of the pipe  
            chRequest,      // Buffer to receive data  
            cbRequest,      // Size of buffer in bytes  
            &cbRead,        // Number of bytes read  
            NULL            // Not overlapped I/O  
            ); 
 
        if (!fFinishRead && ERROR_MORE_DATA != GetLastError()) 
        { 
            dwError = GetLastError(); 
            wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError); 
            goto Cleanup; 
        } 
 
        wprintf(L"Receive %ld bytes from client: \"%s\"\n", cbRead, chRequest); 
 
    } while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA  
 
    //   
    // Send a response from server to client.  
    //   
 
    wchar_t chResponse[] = RESPONSE_MESSAGE; 
    DWORD cbResponse, cbWritten; 
    cbResponse = sizeof(chResponse); 
 
    if (!WriteFile( 
        hNamedPipe,     // Handle of the pipe  
        chResponse,     // Buffer to write  
        cbResponse,     // Number of bytes to write   
        &cbWritten,     // Number of bytes written   
        NULL            // Not overlapped I/O  
        )) 
    { 
        dwError = GetLastError(); 
        wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwError); 
        goto Cleanup; 
    } 
 
    wprintf(L"Send %ld bytes to client: \"%s\"\n", cbWritten, chResponse); 
 
    // Flush the pipe to allow the client to read the pipe's contents   
    // before disconnecting. Then disconnect the client's connection.   
    FlushFileBuffers(hNamedPipe); 
    DisconnectNamedPipe(hNamedPipe); 
 
Cleanup: 
 
    // Centralized cleanup for all allocated resources.  
    if (pSa != NULL) 
    { 
        FreePipeSecurity(pSa); 
        pSa = NULL; 
    } 
    if (hNamedPipe != INVALID_HANDLE_VALUE) 
    { 
        CloseHandle(hNamedPipe); 
        hNamedPipe = INVALID_HANDLE_VALUE; 
    } 
 
    return dwError; 

 
 
//  
//   FUNCTION: CreatePipeSecurity(PSECURITY_ATTRIBUTES *)  
//  
//   PURPOSE: The CreatePipeSecurity function creates and initializes a new   
//   SECURITY_ATTRIBUTES structure to allow Authenticated Users read and   
//   write access to a pipe, and to allow the Administrators group full   
//   access to the pipe.  
//  
//   PARAMETERS:  
//   * ppSa - output a pointer to a SECURITY_ATTRIBUTES structure that allows   
//     Authenticated Users read and write access to a pipe, and allows the   
//     Administrators group full access to the pipe. The structure must be   
//     freed by calling FreePipeSecurity.  
//  
//   RETURN VALUE: Returns TRUE if the function succeeds.  
//  
//   EXAMPLE CALL:  
//  
//     PSECURITY_ATTRIBUTES pSa = NULL;  
//     if (CreatePipeSecurity(&pSa))  
//     {  
//         // Use the security attributes  
//         // ...  
//  
//         FreePipeSecurity(pSa);  
//     }  
//  
BOOL CreatePipeSecurity(PSECURITY_ATTRIBUTES *ppSa) 

    BOOL fSucceeded = TRUE; 
    DWORD dwError = ERROR_SUCCESS; 
 
    PSECURITY_DESCRIPTOR pSd = NULL; 
    PSECURITY_ATTRIBUTES pSa = NULL; 
 
    // Define the SDDL for the security descriptor.  
    PCWSTR szSDDL = L"D:"       // Discretionary ACL  
        L"(A;OICI;GRGW;;;AU)"   // Allow read/write to authenticated users  
        L"(A;OICI;GA;;;BA)";    // Allow full control to administrators  
 
    if (!ConvertStringSecurityDescriptorToSecurityDescriptor(szSDDL,  
        SDDL_REVISION_1, &pSd, NULL)) 
    { 
        fSucceeded = FALSE; 
        dwError = GetLastError(); 
        goto Cleanup; 
    } 
     
    // Allocate the memory of SECURITY_ATTRIBUTES.  
    pSa = (PSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(*pSa)); 
    if (pSa == NULL) 
    { 
        fSucceeded = FALSE; 
        dwError = GetLastError(); 
        goto Cleanup; 
    } 
 
    pSa->nLength = sizeof(*pSa); 
    pSa->lpSecurityDescriptor = pSd; 
    pSa->bInheritHandle = FALSE; 
 
    *ppSa = pSa; 
 
Cleanup: 
    // Clean up the allocated resources if something is wrong.  
    if (!fSucceeded) 
    { 
        if (pSd) 
        { 
            LocalFree(pSd); 
            pSd = NULL; 
        } 
        if (pSa) 
        { 
            LocalFree(pSa); 
            pSa = NULL; 
        } 
 
        SetLastError(dwError); 
    } 
     
    return fSucceeded; 

 
 
//  
//   FUNCTION: FreePipeSecurity(PSECURITY_ATTRIBUTES)  
//  
//   PURPOSE: The FreePipeSecurity function frees a SECURITY_ATTRIBUTES   
//   structure that was created by the CreatePipeSecurity function.   
//  
//   PARAMETERS:  
//   * pSa - pointer to a SECURITY_ATTRIBUTES structure that was created by   
//     the CreatePipeSecurity function.   
//  
void FreePipeSecurity(PSECURITY_ATTRIBUTES pSa) 

    if (pSa) 
    { 
        if (pSa->lpSecurityDescriptor) 
        { 
            LocalFree(pSa->lpSecurityDescriptor); 
        } 
        LocalFree(pSa); 
    } 

#pragma region Includes
#include <stdio.h>
#include <windows.h>
#include <sddl.h>
#pragma endregion


// The full name of the pipe in the format of \\servername\pipe\pipename.
#define SERVER_NAME         L"."
#define PIPE_NAME           L"SamplePipe"
#define FULL_PIPE_NAME      L"\\\\" SERVER_NAME L"\\pipe\\" PIPE_NAME

#define BUFFER_SIZE     1024

// Response message from client to server. '\0' is appended in the end
// because the client may be a native C++ application that expects NULL
// termiated string.
#define RESPONSE_MESSAGE    L"Default response from server"


BOOL CreatePipeSecurity(PSECURITY_ATTRIBUTES *);
void FreePipeSecurity(PSECURITY_ATTRIBUTES);


int wmain(int argc, wchar_t* argv[])
{
    DWORD dwError = ERROR_SUCCESS;
    PSECURITY_ATTRIBUTES pSa = NULL;
    HANDLE hNamedPipe = INVALID_HANDLE_VALUE;

    // Prepare the security attributes (the lpSecurityAttributes parameter in
    // CreateNamedPipe) for the pipe. This is optional. If the
    // lpSecurityAttributes parameter of CreateNamedPipe is NULL, the named
    // pipe gets a default security descriptor and the handle cannot be
    // inherited. The ACLs in the default security descriptor of a pipe grant
    // full control to the LocalSystem account, (elevated) administrators,
    // and the creator owner. They also give only read access to members of
    // the Everyone group and the anonymous account. However, if you want to
    // customize the security permission of the pipe, (e.g. to allow
    // Authenticated Users to read from and write to the pipe), you need to
    // create a SECURITY_ATTRIBUTES structure.
    if (!CreatePipeSecurity(&pSa))
    {
        dwError = GetLastError();
        wprintf(L"CreatePipeSecurity failed w/err 0x%08lx\n", dwError);
        goto Cleanup;
    }

    // Create the named pipe.
    hNamedPipe = CreateNamedPipe(
        FULL_PIPE_NAME,             // Pipe name.
        PIPE_ACCESS_DUPLEX,         // The pipe is duplex; both server and
                                    // client processes can read from and
                                    // write to the pipe
        PIPE_TYPE_MESSAGE |         // Message type pipe
        PIPE_READMODE_MESSAGE |     // Message-read mode
        PIPE_WAIT,                  // Blocking mode is enabled
        PIPE_UNLIMITED_INSTANCES,   // Max. instances
        BUFFER_SIZE,                // Output buffer size in bytes
        BUFFER_SIZE,                // Input buffer size in bytes
        NMPWAIT_USE_DEFAULT_WAIT,   // Time-out interval
        pSa                         // Security attributes
        );

    if (hNamedPipe == INVALID_HANDLE_VALUE)
    {
        dwError = GetLastError();
        wprintf(L"Unable to create named pipe w/err 0x%08lx\n", dwError);
        goto Cleanup;
    }

    wprintf(L"The named pipe (%s) is created.\n", FULL_PIPE_NAME);

    // Wait for the client to connect.
    wprintf(L"Waiting for the client's connection...\n");
    if (!ConnectNamedPipe(hNamedPipe, NULL))
    {
        if (ERROR_PIPE_CONNECTED != GetLastError())
        {
            dwError = GetLastError();
            wprintf(L"ConnectNamedPipe failed w/err 0x%08lx\n", dwError);
            goto Cleanup;
        }
    }
    wprintf(L"Client is connected.\n");

    //
    // Receive a request from client.
    //

    BOOL fFinishRead = FALSE;
    do
    {
        wchar_t chRequest[BUFFER_SIZE];
        DWORD cbRequest, cbRead;
        cbRequest = sizeof(chRequest);

        fFinishRead = ReadFile(
            hNamedPipe,     // Handle of the pipe
            chRequest,      // Buffer to receive data
            cbRequest,      // Size of buffer in bytes
            &cbRead,        // Number of bytes read
            NULL            // Not overlapped I/O
            );

        if (!fFinishRead && ERROR_MORE_DATA != GetLastError())
        {
            dwError = GetLastError();
            wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError);
            goto Cleanup;
        }

        wprintf(L"Receive %ld bytes from client: \"%s\"\n", cbRead, chRequest);

    } while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA

    //
    // Send a response from server to client.
    //

    wchar_t chResponse[] = RESPONSE_MESSAGE;
    DWORD cbResponse, cbWritten;
    cbResponse = sizeof(chResponse);

    if (!WriteFile(
        hNamedPipe,     // Handle of the pipe
        chResponse,     // Buffer to write
        cbResponse,     // Number of bytes to write
        &cbWritten,     // Number of bytes written
        NULL            // Not overlapped I/O
        ))
    {
        dwError = GetLastError();
        wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwError);
        goto Cleanup;
    }

    wprintf(L"Send %ld bytes to client: \"%s\"\n", cbWritten, chResponse);

    // Flush the pipe to allow the client to read the pipe's contents
    // before disconnecting. Then disconnect the client's connection.
    FlushFileBuffers(hNamedPipe);
    DisconnectNamedPipe(hNamedPipe);

Cleanup:

    // Centralized cleanup for all allocated resources.
    if (pSa != NULL)
    {
        FreePipeSecurity(pSa);
        pSa = NULL;
    }
    if (hNamedPipe != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hNamedPipe);
        hNamedPipe = INVALID_HANDLE_VALUE;
    }

    return dwError;
}


//
//   FUNCTION: CreatePipeSecurity(PSECURITY_ATTRIBUTES *)
//
//   PURPOSE: The CreatePipeSecurity function creates and initializes a new
//   SECURITY_ATTRIBUTES structure to allow Authenticated Users read and
//   write access to a pipe, and to allow the Administrators group full
//   access to the pipe.
//
//   PARAMETERS:
//   * ppSa - output a pointer to a SECURITY_ATTRIBUTES structure that allows
//     Authenticated Users read and write access to a pipe, and allows the
//     Administrators group full access to the pipe. The structure must be
//     freed by calling FreePipeSecurity.
//
//   RETURN VALUE: Returns TRUE if the function succeeds.
//
//   EXAMPLE CALL:
//
//     PSECURITY_ATTRIBUTES pSa = NULL;
//     if (CreatePipeSecurity(&pSa))
//     {
//         // Use the security attributes
//         // ...
//
//         FreePipeSecurity(pSa);
//     }
//
BOOL CreatePipeSecurity(PSECURITY_ATTRIBUTES *ppSa)
{
    BOOL fSucceeded = TRUE;
    DWORD dwError = ERROR_SUCCESS;

    PSECURITY_DESCRIPTOR pSd = NULL;
    PSECURITY_ATTRIBUTES pSa = NULL;

    // Define the SDDL for the security descriptor.
    PCWSTR szSDDL = L"D:"       // Discretionary ACL
        L"(A;OICI;GRGW;;;AU)"   // Allow read/write to authenticated users
        L"(A;OICI;GA;;;BA)";    // Allow full control to administrators

    if (!ConvertStringSecurityDescriptorToSecurityDescriptor(szSDDL,
        SDDL_REVISION_1, &pSd, NULL))
    {
        fSucceeded = FALSE;
        dwError = GetLastError();
        goto Cleanup;
    }
   
    // Allocate the memory of SECURITY_ATTRIBUTES.
    pSa = (PSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(*pSa));
    if (pSa == NULL)
    {
        fSucceeded = FALSE;
        dwError = GetLastError();
        goto Cleanup;
    }

    pSa->nLength = sizeof(*pSa);
    pSa->lpSecurityDescriptor = pSd;
    pSa->bInheritHandle = FALSE;

    *ppSa = pSa;

Cleanup:
    // Clean up the allocated resources if something is wrong.
    if (!fSucceeded)
    {
        if (pSd)
        {
            LocalFree(pSd);
            pSd = NULL;
        }
        if (pSa)
        {
            LocalFree(pSa);
            pSa = NULL;
        }

        SetLastError(dwError);
    }
   
    return fSucceeded;
}


//
//   FUNCTION: FreePipeSecurity(PSECURITY_ATTRIBUTES)
//
//   PURPOSE: The FreePipeSecurity function frees a SECURITY_ATTRIBUTES
//   structure that was created by the CreatePipeSecurity function.
//
//   PARAMETERS:
//   * pSa - pointer to a SECURITY_ATTRIBUTES structure that was created by
//     the CreatePipeSecurity function.
//
void FreePipeSecurity(PSECURITY_ATTRIBUTES pSa)
{
    if (pSa)
    {
        if (pSa->lpSecurityDescriptor)
        {
            LocalFree(pSa->lpSecurityDescriptor);
        }
        LocalFree(pSa);
    }
}CppNamedPipeClient.cpp


[cpp]  #pragma region Includes  
#include <stdio.h>  
#include <windows.h>  
#pragma endregion  
 
 
// The full name of the pipe in the format of \\servername\pipe\pipename.  
#define SERVER_NAME         L"."  
#define PIPE_NAME           L"SamplePipe"  
#define FULL_PIPE_NAME      L"\\\\" SERVER_NAME L"\\pipe\\" PIPE_NAME  
 
#define BUFFER_SIZE     1024  
 
// Request message from client to server.  
#define REQUEST_MESSAGE     L"Default request from client"  
 
 
int wmain(int argc, wchar_t* argv[]) 

    HANDLE hPipe = INVALID_HANDLE_VALUE; 
    DWORD dwError = ERROR_SUCCESS; 
 
    // Try to open the named pipe identified by the pipe name.  
    while (TRUE)  
    { 
        hPipe = CreateFile(  
            FULL_PIPE_NAME,                 // Pipe name   
            GENERIC_READ | GENERIC_WRITE,   // Read and write access  
            0,                              // No sharing   
            NULL,                           // Default security attributes  
            OPEN_EXISTING,                  // Opens existing pipe  
            0,                              // Default attributes  
            NULL                            // No template file  
            ); 
 
        // If the pipe handle is opened successfully ...  
        if (hPipe != INVALID_HANDLE_VALUE) 
        { 
            wprintf(L"The named pipe (%s) is connected.\n", FULL_PIPE_NAME); 
            break; 
        } 
 
        dwError = GetLastError(); 
 
        // Exit if an error other than ERROR_PIPE_BUSY occurs.  
        if (ERROR_PIPE_BUSY != dwError) 
        { 
            wprintf(L"Unable to open named pipe w/err 0x%08lx\n", dwError); 
            goto Cleanup; 
        } 
 
        // All pipe instances are busy, so wait for 5 seconds.  
        if (!WaitNamedPipe(FULL_PIPE_NAME, 5000)) 
        { 
            dwError = GetLastError(); 
            wprintf(L"Could not open pipe: 5 second wait timed out."); 
            goto Cleanup; 
        } 
    } 
 
    // Set the read mode and the blocking mode of the named pipe. In this   
    // sample, we set data to be read from the pipe as a stream of messages.  
    DWORD dwMode = PIPE_READMODE_MESSAGE; 
    if (!SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL)) 
    { 
        dwError = GetLastError(); 
        wprintf(L"SetNamedPipeHandleState failed w/err 0x%08lx\n", dwError); 
        goto Cleanup; 
    } 
 
    //   
    // Send a request from client to server  
    //   
 
    wchar_t chRequest[] = REQUEST_MESSAGE; 
    DWORD cbRequest, cbWritten; 
    cbRequest = sizeof(chRequest); 
 
    if (!WriteFile( 
        hPipe,                      // Handle of the pipe  
        chRequest,                  // Message to be written  
        cbRequest,                  // Number of bytes to write  
        &cbWritten,                 // Number of bytes written  
        NULL                        // Not overlapped  
        )) 
    { 
        dwError = GetLastError(); 
        wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwError); 
        goto Cleanup; 
    } 
 
    wprintf(L"Send %ld bytes to server: \"%s\"\n", cbWritten, chRequest); 
 
    //  
    // Receive a response from server.  
    //   
 
    BOOL fFinishRead = FALSE; 
    do 
    { 
        wchar_t chResponse[BUFFER_SIZE]; 
        DWORD cbResponse, cbRead; 
        cbResponse = sizeof(chResponse); 
 
        fFinishRead = ReadFile( 
            hPipe,                  // Handle of the pipe  
            chResponse,             // Buffer to receive the reply  
            cbResponse,             // Size of buffer in bytes  
            &cbRead,                // Number of bytes read   
            NULL                    // Not overlapped   
            ); 
 
        if (!fFinishRead && ERROR_MORE_DATA != GetLastError()) 
        { 
            dwError = GetLastError(); 
            wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError); 
            goto Cleanup; 
        } 
 
        wprintf(L"Receive %ld bytes from server: \"%s\"\n", cbRead, chResponse); 
 
    } while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA  
 
Cleanup: 
 
    // Centralized cleanup for all allocated resources.  
    if (hPipe != INVALID_HANDLE_VALUE) 
    { 
        CloseHandle(hPipe); 
        hPipe = INVALID_HANDLE_VALUE; 
    } 
 
    return dwError; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved