2011-08-05 55 views
6

名前付きパイプサーバーとクライアントがあります。 (これをVC++で行う)。名前付きパイプに再接続する際の問題

サーバ

  1. CreateNamedPipe
  2. ConnectNamedPipe
  3. のWriteFile
  4. 切断
  5. 2からクリエ

4を繰り返しNTはありません

  1. のCreateFile
  2. のReadFile
次のように実行順序がある

  1. サーバ - CreateNamedPipe
  2. クライアント - のCreateFile
  3. サーバ - - ConnectNamedPipe(すぐにclとして返す必要がありますientはすでに)
  4. サーバー接続されている - のWriteFileを
  5. クライアント - のReadFile
  6. サーバ - DisconnectNamedPipe
  7. クライアント - CloseHandleを
  8. 後藤2

これは最初のために正常に動作します時間。ただし、クライアントが2回目の接続を試みると問題が発生します。クライアントがの前にの前に接続(CreateFile)しようとすると、サーバーはConnectNamedPipeを実行しましたが(のdisconnectnamedpipeの後に)、ERROR_PIPE_BUSYを取得します。サーバーがConnectNamedPipeを呼び出した後、クライアントがcreatefileを呼び出すと機能します。

(DisconnectNamedPipeの後に)ConnectNamedPipeという名前のサーバーの前にクライアントを接続する(CreateFile)ことができますか?

Serverコード:

pipe_handle.pipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\testpipe1"), 
       PIPE_ACCESS_OUTBOUND | 
       FILE_FLAG_OVERLAPPED,  // read/write access 
       PIPE_TYPE_MESSAGE |   // message type pipe 
       PIPE_READMODE_MESSAGE |  // message-read mode 
       PIPE_WAIT,     // blocking mode 
       PIPE_UNLIMITED_INSTANCES,  // max. instances 
       BUFFER_SIZE,     // output buffer size 
       BUFFER_SIZE,     // input buffer size 
       2000,    // client time-out 
       NULL); 

if (pipe_handle.pipe == INVALID_HANDLE_VALUE) { 
    std::cout << "Error while creating pipe" << std::endl; 
    return -1; 
} 
std::cout <<"Connecting to named pipe" << std::endl; 

std::cout<< "Somebody connected to named pipe" << std::endl; 

int ac; 

for (ac=0; ac<2; ac++) { 

    char a[25]; 
    // Wait for some input. This helps me to start the client in other terminal. 
    cin >> a; 
    cout << "Connecting..." << endl; 

    ConnectNamedPipe(pipe_handle.pipe, 0); 

    cout << "Connect pipe returned." << endl; 

    // Wait for some input. 
    cin >> a; 
    string message = "Test message"; 
    DWORD bytes_written; 

    if (!WriteFile(pipe_handle.pipe, message.c_str(), message.size(), 
        &bytes_written, NULL)) { 

     DWORD er = GetLastError(); 
     char errs[200]; 
     sprintf(errs, "Error : %ld", er); 
     std::cout << "Error communicating to client."; 
     std::cout << errs; 
    } 
    std::cout << "Written to pipe"; 
    FlushFileBuffers(pipe_handle.pipe); 
    if (!DisconnectNamedPipe(pipe_handle.pipe)) { 
     std::cout << "Disconnect failed"<< GetLastError() << endl; 
    } else { 
     std::cout << "Disconnect successful"<<endl; 
    } 
} 

クライアントコード:あなたは、クライアントでのCreateFile()の呼び出しにERROR_PIPE_BUSYを取得する場合

while (1) { 

    std::cout << "Returned" << std::endl; 
    hPipe = CreateFile( 
       lpszPipename, // pipe name 
       GENERIC_READ, 
       0,    // no sharing 
       NULL,   // default security attributes 
       OPEN_EXISTING, // opens existing pipe 
       FILE_FLAG_OVERLAPPED,    // default attributes 
       NULL);   // no template file 

    // Break if the pipe handle is valid. 

    if (hPipe != INVALID_HANDLE_VALUE) 
     break; 


    // Exit if an error other than ERROR_PIPE_BUSY occurs. 

    if (GetLastError() != ERROR_PIPE_BUSY) { 
     std::cout<< "Could not open pipe " << GetLastError() << std::endl; 
     return -1; 
    } 

    // All pipe instances are busy, so wait for sometime. 

    if (! WaitNamedPipe(lpszPipename, NMPWAIT_USE_DEFAULT_WAIT)) { 
     std::cout<< "Could not open pipe: wait timed out." << std::endl; 
    } 
} 

OVERLAPPED ol1; 

memset(&ol1, 0, sizeof(ol1)); 
ol1.Offset = 0; 
ol1.OffsetHigh = 0; 
ol1.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 

HANDLE events[1]; 
events[0] = ol1.hEvent; 
cbToWrite = (lstrlen(message)+1)*sizeof(TCHAR); 

DWORD bytes_to_read = 2000; 
char * buf = reinterpret_cast<char *>(malloc(bytes_to_read)); 
DWORD bytes_read; 

std::cout << "Waiting for read" << std::endl; 
bool a = ReadFile(hPipe, buf, bytes_to_read, &bytes_read, &ol1); 


if (! fSuccess) { 
    std::cout << "WriteFile to pipe failed. GLE " << GetLastError() << std::endl; 
} 
std::cout << "Waiting for multiple objects" << std::endl; 
WaitForMultipleObjects(1, events, FALSE, INFINITE); 
std::cout << "multiple objects returned" << std::endl; 
printf("\nMessage sent to server"); 
CancelIo(hPipe); 
CloseHandle(hPipe); 

答えて

8

が、あなたはときにそれを再試行しWaitNamedPipe()を呼び出すとする必要があります戻る。 WaitNamedPipe()からの戻り値が0の場合は、パイプが使用可能にならずにタイムアウトしたことを意味します。 NMPWAIT_WAIT_FOREVERをタイムアウトとして渡すと、これは起こりません。

また、パイプがWaitNamedPipe()が返ってからCreateFile()を呼び出すまでに再びビジーになることがあることに注意する必要があります。したがって、あなたはループでそれを行う必要があります。

while (true) 
{ 
    hPipe = CreateFile(pipeName, 
         GENERIC_READ | GENERIC_WRITE, 
         0, 
         0, 
         OPEN_EXISTING, 
         FILE_ATTRIBUTE_NORMAL, 
         0); 
    if (hPipe == INVALID_HANDLE_VALUE) 
    { 
     if (GetLastError() == ERROR_PIPE_BUSY) 
     { 
      if (!WaitNamedPipe(pipeName, NMPWAIT_USE_DEFAULT_WAIT)) 
       continue; // timeout, try again 
     } 
     else 
      return false; // error 
    } 
    else 
     break; // success 
} 

EDIT:このよう

私はあなたのコードを簡素化し、今では正常に動作します。作業中のサーバーとクライアントが続きます。

サーバー:

#include <windows.h> 
#include <stdio.h> 

int main(void) 
{ 
    HANDLE pipe; 
    const DWORD BUFFER_SIZE = 1024; 

    pipe = CreateNamedPipe("\\\\.\\pipe\\testpipe1", 
            PIPE_ACCESS_OUTBOUND | 
            FILE_FLAG_OVERLAPPED,   // read/write access 
            PIPE_TYPE_MESSAGE |    // message type pipe 
            PIPE_READMODE_MESSAGE |   // message-read mode 
            PIPE_WAIT,       // blocking mode 
            PIPE_UNLIMITED_INSTANCES, // max. instances 
            BUFFER_SIZE,      // output buffer size 
            BUFFER_SIZE,      // input buffer size 
            2000,     // client time-out 
            NULL); 

    if (pipe == INVALID_HANDLE_VALUE) 
    { 
     printf("Error while creating pipe\n"); 
     return -1; 
    } 
    printf("Connecting to named pipe\n"); 

    int ac; 

    for (ac=0; ac<2; ac++) 
    { 
     // Wait for some input. This helps me to start the client in other terminal. 
     printf("Connecting...\n"); 

     ConnectNamedPipe(pipe, 0); 

     printf("Connect pipe returned.\n"); 

     // Wait for some input. 
     char * message = "Test message"; 
     DWORD bytes_written; 

     if (!WriteFile(pipe, message, strlen(message)+1, &bytes_written, NULL)) 
     { 

      DWORD er = GetLastError(); 
      char errs[200]; 
      sprintf_s(errs, "Error : %ld", er); 
      printf("Error communicating to client.\n"); 
      printf(errs); 
     } 
     printf("Written to pipe\n"); 
     FlushFileBuffers(pipe); 
     if (!DisconnectNamedPipe(pipe)) 
     { 
      printf("Disconnect failed %d\n", GetLastError()); 
     } 
     else 
     { 
      printf("Disconnect successful\n"); 
     } 
    } 
} 

クライアント:あなたはチェーンを使用する必要があり、接続中断することを決定し、サーバー側で

#include <windows.h> 
#include <stdio.h> 

int main(void) 
{ 
    HANDLE hPipe; 

    while (1) 
    { 

     printf("Returned\n"); 
     hPipe = CreateFile("\\\\.\\pipe\\testpipe1", 
           GENERIC_READ, 
           0,     // no sharing 
           NULL,    // default security attributes 
           OPEN_EXISTING, // opens existing pipe 
           0,    // default attributes 
           NULL);   // no template file 

     // Break if the pipe handle is valid. 

     if (hPipe != INVALID_HANDLE_VALUE) 
      break; 


     // Exit if an error other than ERROR_PIPE_BUSY occurs. 

     if (GetLastError() != ERROR_PIPE_BUSY) 
     { 
      printf("Could not open pipe %d\n", GetLastError()); 
      return -1; 
     } 

     // All pipe instances are busy, so wait for sometime. 

     if (! WaitNamedPipe("\\\\.\\pipe\\testpipe1", NMPWAIT_USE_DEFAULT_WAIT)) 
     { 
      printf("Could not open pipe: wait timed out.\n"); 
     } 
    } 


    char *message = "hello"; 
    DWORD cbToWrite = (strlen(message)+1)*sizeof(message[0]); 

    DWORD bytes_to_read = 2000; 
    char * buf = reinterpret_cast<char *>(malloc(bytes_to_read)); 
    DWORD bytes_read; 

    printf("Waiting for read\n"); 
    bytes_read = 0; 
    ReadFile(hPipe, buf, bytes_to_read, &bytes_read, 0); 

    if (bytes_read <= 0) 
    { 
     printf("ReadFile from pipe failed. GLE \n"); 
    } 
    else 
     printf("Read %d bytes: %s\n", bytes_read, buf); 

    CloseHandle(hPipe); 
    return 0; 
} 
+0

返信いただきありがとうございます。このコードで試しましたが、クライアントはERROR_PIPE_BUSYを取得し続けます。サーバーがConnectNamedPipe()を呼び出すと、クライアントはエラーなくCreateFile()を正常に実行できます。 – Ashwin

+0

質問をサーバーとクライアントのコード – Ashwin

+0

に更新しました@Ashwin:編集する編集を参照してください。 –

-2

1) CloseHandle(Pipe);

2)DisconnectNamedPipe(Pipe);

関連する問題