2010-01-18 283 views
2

我已經創建了一個命名管道與以下標誌:如何獲取要在命名管道中讀取(可靠)數據的長度?

  • PIPE_ACCESS_DUPLEX - 兩側的讀/寫訪問
  • PIPE_TYPE_MESSAGE - 消息類型讀
  • PIPE_WAIT - 阻塞讀\寫

從服務器端我打電話ConnectNamedPipe並等待客戶端連接。

從客戶端我打電話CallNamedPipe連接到服務器並寫入長度爲N

的數據在服務器端:客戶端連接後

  • PeekNamedPipe被稱爲獲得長度分配給讀取數據緩衝區的緩衝區。
  • 得到確切的緩衝區大小(N)後,我分配長度爲N的緩衝區並調用ReadFile以從Pipe中讀取數據。

問題:

  • 問題是, - 對單處理器機器的PeekNamedPipe API返回緩衝區長度爲0。由於此後的ReadFile失敗。
  • 經過一番調查後,我發現由於某種競爭條件,PeekNamedPipe API甚至在數據被客戶端放到管道之前被調用。
  • 任何想法如何解決這種競爭條件?我需要調用PeekNamedPipe來獲取緩衝區大小,並且在數據可用之前不能調用PeekNamedPipe。

我想過介紹自定義頭來指示消息本身的緩衝區長度,但這聽起來很多變化。

有沒有更好更可靠的方法來獲取從管道中讀取數據的長度?

回答

0

在任何情況下在報頭中分組大小都是一個好主意,使得協議減少對傳輸層的依賴。 或者,如果客戶端發送數據並關閉管道,則可以使用ReadFile將其累積到緩衝區中,直到EOF。

1

這聽起來像你想要的同步I/O。只要讓Windows在數據可用時通知您,並在當時偷看。

6

您可以通過命名管道獲得大量競態條件。你必須在你的代碼中處理它們。可能性:

  • ConnectNamedPipe()在服務器端可以返回ERROR_PIPE_CONNECTED如果客戶端管理的CreateNamedPipe時()調用後向右連接。只要把它當作連接。
  • 客戶端的WaitNamedPipe在超時時不會設置錯誤。假設超時。
  • 即使在成功調用WaitNamedPipe()後,客戶端的CreateFile()可能會返回ERROR_PIPE_BUSY,前提是另一個客戶端設法首先獲取管道。回到WaitNamedPipe狀態。
  • 如果客戶端已經看到消息並關閉了管道,FlushFileBuffers()可能會返回ERROR_PIPE_NOT_CONNECTED。忽略這一點。
  • 重疊的ReadFile()調用可能立即完成並且不返回ERROR_IO_PENDING。考慮讀取完成。
  • 如果服務器尚未寫入管道,PeekNamedPipe()可能會返回0。睡眠(1)並重復。
相關問題