2017-03-06 28 views
0

我想發送消息到服務器並使用命名管道讀取它。當我使用WriteFile函數時,消息到達服務器,但TransactNamedPipe失敗,錯誤230(ERROR_BAD_PIPE)並且CallNamedPipe失敗,錯誤87(INVALID_PARAMETER)或231(PIPE_BUSY)。我試過MSDN的例子,很多其他的東西,但仍然沒有結果。請幫忙。CallNamedPipe和TransactNamedPipe不起作用

客戶:

#include <windows.h> 
#include <stdio.h> 
#include <conio.h> 
#include <tchar.h> 
#include <string> 

#define BUFSIZE 512 

int _tmain(int argc, TCHAR *argv[]) 
{ 
    OVERLAPPED ov; 
    ZeroMemory(&ov, sizeof(OVERLAPPED)); 

    HANDLE hPipe; 
    // Try to open a named pipe; wait for it, if necessary. 
    while (1) 
    { 
     hPipe = CreateFile(
      L"\\\\.\\pipe\\PipeTest", // pipe name 
      GENERIC_READ | // read and write access 
      GENERIC_WRITE, 
      0,    // no sharing 
      NULL,   // default security attributes 
      OPEN_EXISTING, // opens existing pipe 
      FILE_FLAG_OVERLAPPED,    
      NULL);   // no template file 

          // Break if the pipe handle is valid. 
     if (hPipe != INVALID_HANDLE_VALUE) 
      break; 

     DWORD lastErr = GetLastError(); 

     // Exit if an error other than ERROR_PIPE_BUSY occurs. 
     if (GetLastError() != ERROR_PIPE_BUSY) 
     { 
      printf("Could not open pipe\n"); 
      return 0; 
     } 

     // All pipe instances are busy, so wait for 2 seconds. 
     if (!WaitNamedPipe(L"\\\\.\\pipe\\PipeTest", 2000)) 
     { 
      printf("Could not open pipe\n"); 
      return 0; 
     } 
    } 

    std::wstring s; 
    s.resize(1024); 
    DWORD cbRead; 

    BOOL fSuccess = TransactNamedPipe(
     hPipe,     // pipe handle 
     L"Hello",    // message to server 
     sizeof(wchar_t) * 5, // message length 
     &s[0], 
     s.size() * sizeof(wchar_t), 
     &cbRead,    // bytes read 
     &ov);     // not overlapped 

    DWORD lastErr = GetLastError(); 
    GetOverlappedResult(hPipe, &ov, &cbRead, TRUE); 
    DWORD lastErr2 = GetLastError(); 

    CloseHandle(hPipe); 

    return 0; 
} 

服務器:

#include <iostream> 
#include <string> 
#include <Windows.h> 

const std::wstring pipeName = L"\\\\.\\pipe\\PipeTest"; 

int main(void) 
{ 
    HANDLE hPipe; 
    wchar_t buffer[256]; 
    DWORD dwRead; 

    OVERLAPPED ov; 
    ZeroMemory(&ov, sizeof(OVERLAPPED)); 

    hPipe = CreateNamedPipe(pipeName.c_str(), 
     PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists... 
     PIPE_WAIT, 
     1, 
     1024 * 16, 
     1024 * 16, 
     NMPWAIT_USE_DEFAULT_WAIT, 
     NULL); 

    if (hPipe != INVALID_HANDLE_VALUE) 
    { 
     if (ConnectNamedPipe(hPipe, &ov) != FALSE) // wait for someone to connect to the pipe 
     { 
      while (ReadFile(hPipe, buffer, 255, &dwRead, &ov) != FALSE) 
      { 
       WriteFile(hPipe, L"lalala", 6 * sizeof(wchar_t), &dwRead, &ov); 

       DWORD lastErr1 = GetLastError(); 
       GetOverlappedResult(hPipe, &ov, &dwRead, TRUE); 
       DWORD lastrr2 = GetLastError(); 

       printf("%s", buffer); 
      } 
     } 

     DisconnectNamedPipe(hPipe); 
    } 

    return 0; 
} 
+0

是的,這些函數可正常工作。但是,您的程序有缺陷。 –

回答

1

,如果你瞭解TransactNamedPipe

如果服務器沒有創造管材作爲 消息類型TransactNamedPipe失敗管道或如果管道手柄不是在消息讀取模式。

CallNamedPipe

調用CallNamedPipe是相當於調用的CreateFile(或 WaitNamedPipe,如果的CreateFile不能立即打開管道), TransactNamedPipe,和CloseHandle的功能

所以這個功能只能工作消息類型管道

但是當您創建服務器管道時,您使用PIPE_TYPE_BYTE | PIPE_READMODE_BYTE 所以CallNamedPipe和/或TransactNamedPipe必須失敗。

您需要使用ReadFile/WriteFile代替。或使用標記PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE創建服務器,並調用SetNamedPipeHandleState作爲客戶端句柄以設置其消息讀取模式(使用PIPE_READMODE_MESSAGE

+0

當我將PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE放入CreateNamedPipe時,立即得到錯誤87 - invalid_parameter。 – banana36

+0

您發佈的代碼在第二個參數中傳遞管道類型和模式,它們必須在第三個參數中傳遞。它似乎只能工作,因爲「PIPE_TYPE_BYTE」和「PIPE_READMODE_BYTE」碰巧等於0。 –