2012-03-12 184 views
3

我想開始使用命名管道工作,我將需要使用它們在未來我的一個項目。如何使用命名管道(C++服務器,C#客戶端)

目前我有等待,直到客戶端連接,併發送經測試消息一個C++服務器。我大致遵循這個tutorial開始。相關代碼如下:

#define MESSAGE L"TestMessage" 

HANDLE hnamedPipe = INVALID_HANDLE_VALUE; 

hnamedPipe = CreateNamedPipe(
    L"\\\\.\\pipe\\testpipe", 
    PIPE_ACCESS_DUPLEX, 
    PIPE_TYPE_MESSAGE| 
    PIPE_READMODE_MESSAGE| 
    PIPE_WAIT, 
    PIPE_UNLIMITED_INSTANCES, 
    1024, 
    1024, 
    NMPWAIT_USE_DEFAULT_WAIT, 
    NULL); 

if(hnamedPipe == INVALID_HANDLE_VALUE) 
{ 
     cout << "Failed" << endl; 
} 

while(true) 
{ 
    cout<< "Waiting for client"<< endl; 

    if(!ConnectNamedPipe(hnamedPipe,NULL)) 
    { 
     if(ERROR_PIPE_CONNECTED != GetLastError()) 
     { 
     cout << "FAIL"<< endl; 
     } 
    } 

    cout<<"Connected!"<<endl; 

    //Send over the message 
    wchar_t chResponse[] = MESSAGE; 
    DWORD cbResponse,cbWritten; 
    cbResponse = sizeof(chResponse); 

    if(!WriteFile(
    hnamedPipe, 
    chResponse, 
    cbResponse, 
    &cbWritten, 
    NULL)) 
    { 
     wprintf(L"failiure w/err 0x%08lx\n",GetLastError); 
    } 
    cout<<"Sent bytes :)" << endl; 
} 

客戶端代碼(C#)低於:

 using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut)) 
     { 
      while (true) 
      { 
       Console.WriteLine("Connecting to server..."); 
       pipeClient.Connect(); 

       Console.WriteLine("Connected :)"); 
       Console.WriteLine(pipeClient.ReadByte()); 
       pipeClient.Close(); 
       Console.WriteLine("Closed"); 
      } 

     } 

在我已經得到了客戶端成功連接到服務器的時刻,它打印出的第一個字節。我想知道如何做兩件事情:

  1. 閱讀整個消息 - 我嘗試使用的StreamReader在pipeClient閱讀信息,但它無限期地掛在的ReadLine()。

  2. 連續發送了郵件 - 我希望服務器消息後發送消息給客戶端,這將在一次一個閱讀並打印出來。我有點無能IPC所以剛開始我試圖讓客戶端斷開並重新連接在一段時間(true)循環的服務器,而服務器在一段時間真正的循環在頂部總是等待前一個新的客戶端連接發送另一條消息。我試圖在上面的代碼中。

任何幫助,這將不勝感激。最終的目標是將圖像從服務器發送到客戶端。客戶端然後將它們實時打印到屏幕上。在我嘗試圖像數據之前,我想用簡單的字符串消息來處理這個問題。

編輯:

最後,我希望能夠從客戶端發送信息到服務器,表明它想獲得最新的圖像幀時,服務器將發送了最新的幀的客戶端將其再在屏幕上顯示。所以流程如下:

  1. 客戶端 - >服務器:指示客戶端需要最新的幀信息。 (很簡單,也許是1的無符號整數)
  2. 服務器 - >客戶端:最新的框架信息。 (存儲在一個字節數組RGB字節值640×480圖像)
  3. 客戶端:在顯示器上顯示的幀。
+0

對於你的第一個問題,使用類似'StreamReader'(只有當你的消息是文本時才使用它)。 'StreamReader.ReadToEnd'將從流中讀取所有可用的數據。 – 2012-03-13 00:12:02

+0

嗨,我試過了,但它一直等到C++服務器關閉之前纔打印出所有消息。最終,我希望能夠從客戶端向服務器發送一條消息,表明它想要獲取最新的圖像幀,然後服務器將發送最新的幀,然後客戶端將在屏幕上顯示該幀。 – Jkh2 2012-03-13 15:26:43

回答

4

ReadLine掛起,因爲它正在等待您的測試消息不包含的換行符。

如果您希望服務器不斷髮送消息,只需在WriteFile呼叫周圍放置一個循環即可。您不需要連接多次。同樣的,在客戶端,把循環周圍ReadLine

如果每個消息由一個換行符終止,則應該足夠了文本,但如果你真的想管客戶端短信模式下工作,你需要調用:

pipeClient.ReadMode = PipeTransmissionMode.Message; 

不過,我懷疑這會與StreamReader很好地互動。相反,您應該使用pipeClient.Read讀取單個消息。

更新

要回答新問題:

在服務器上,一旦客戶端連接進入一個循環,其中:

  • 服務器從客戶端不讀。這將阻塞,直到客戶端請求一個幀。
  • 服務器發送一個幀。

在客戶端,一旦它連接到服務器進入一個循環,其中:

  • 客戶端發送一個「請發送幀」的信息。
  • 客戶端從服務器讀取以獲取幀。
  • 客戶端顯示框架。

我不會使用消息模式管道。如果幀的大小是固定的,那麼客戶端就知道要從服務器讀取多少數據。否則,在包含其長度的uint之前插入幀。

+0

@ Jkh2:我已經更新了我的答案。 – arx 2012-03-13 16:39:44

+0

謝謝,我已經將這個邏輯加入到我的代碼中,它工作的很棒:) – Jkh2 2012-03-13 16:53:10

相關問題