[named pipe] .Net 的 named pipe,堪用的第一步。Client 端
經過 Server 端程式的字很多轟炸之後,再來看 Client 端程式會覺得很開心。不但 thread 變少,要考慮的狀況也少很多。復習一下,pipe name 與 pipe direction 的關係。
看圖可以比較清楚的知道,在 Client 端,<pipe name>_1 是 Out,屆時要連接的是 StreamWriter,而 <pipe name>_2 是 In,屆時要連接 StreamReader。正好跟 Server 端程式反過來。由此可以注意到,所謂的 In, Out 是對本身程式而言,而不是對 Pipe 的方向。同一個 pipe,對於 pipe 兩端的程式來說,in,out 就是剛好相反。所以為了自己也為了別人好,就不要把 pipe 取名 xxx_in 或 xxx_out。要是這樣取名字一定會害死人的。
接下來介紹與 server 端連接的函式。Client 端使用的是 NamedPipeClientStream 這個物件。因為 windows 的 pipe 是可以跨電腦的,所以 client 端的 pipe 在呼叫建構函式的時候,是要清楚告知是哪台電腦的 pipe。在這裡選擇三個參數的建構函式。第一個是 host name,輸入 "." 是告知使用本機。在實例化後,只要呼叫 Connect 即可與 server 端連接。在這裡一樣在處理 in 這個 pipe 需要用一個 thread 來呼叫 SubHandleRead。
Sub ConnectToServer()
Dim pipename1 As String = TextBox1.Text & "_1"
Dim pipename2 As String = TextBox1.Text & "_2"
PipeClientIn = New NamedPipeClientStream(".", pipename2, PipeDirection.In)
PipeClientOut = New NamedPipeClientStream(".", pipename1, PipeDirection.Out)Try
UpdateConnectionState(ConnectionState.Waiting)
PipeClientIn.Connect()
PipeClientOut.Connect()
ThreadIn = New Thread(AddressOf SubHandleRead)
ThreadIn.Start()
UpdateConnectionState(ConnectionState.Connected)
Catch ex As Exception
UpdateConnectionState(ConnectionState.Disconnected)
PipeClientIn = Nothing
PipeClientOut = Nothing
End Try
End Sub
因為在 PipeClientIn 斷開之後,不需要自動重連,因此 SubHandleRead 非常簡單,斷開就離開。
Sub SubHandleRead()
Dim RStream As StreamReader
RStream = New StreamReader(PipeClientIn)
While True
Dim ReadStringLine As String = RStream.ReadLine
If ReadStringLine Is Nothing Then
Exit While
End If
UpdateTextBox2State(ReadStringLine)
End While
UpdateConnectionState(ConnectionState.Disconnected)
CleanPipeClient()
End Sub
斷開的情境有兩個。一個是 Client 主動斷開,一個是 Server 主動斷開。
在 Server 主動斷開的情況下,SubHandleRead 裡 RStream.ReadLine 方法會傳回 Nothing,接下來離開迴圈。在更新完 GUI 的資訊後,最好把 PipeClientIn 及 PipeClientOut 都 Close 確保有釋放資源。SubHandleRead 離開後 ThreadIn 也就結束了。
在 Client 主動斷開的情況下,是由 PipeClientIn 執行 Close 方法,接下來 SubHandleRead 裡 RStream.ReadLine 方法會傳回 Nothing,然後離開迴圈。按照道理說,PipeClientIn 及 PipeClientOut 都執行過 Close 了,所以可不用執行 CleanPipeClient()。但因為執行也無妨。同時,離開了 SubHandleRead 後,ThreadIn 也停了,所以可放心不會有問題。
傳送資料的方式很簡單,只要在畫面下方的文字框,輸入文字,按下 Send 鈕就可以了。
Server 端程式跟 Client 端程式的寫法都一樣:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim WStream As StreamWriter
WStream = New StreamWriter(PipeServerOut)
Try
WStream.WriteLine(TextBox3.Text)
TextBox3.Text = ""
WStream.Flush()
Catch ex As Exception
CleanPipeServer()
CleanThread()
UpdateConnectionState(ConnectionState.Disconnected)
End Try
End Sub
到此,基本的 Server 端程式與 Client 端程式的行為都已跟需求一樣。暫時休息一下。
參考:
http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeserverstream.aspx