2013年9月15日 星期日

[named pipe] .Net 的 named pipe,堪用的第一步。Client 端

經過 Server 端程式的字很多轟炸之後,再來看 Client 端程式會覺得很開心。不但 thread 變少,要考慮的狀況也少很多。復習一下,pipe name 與 pipe direction 的關係。

image

看圖可以比較清楚的知道,在 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 鈕就可以了。

image

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

沒有留言:

張貼留言