名前付きパイプを使ったクライアントプログラムとの通信の説明は以下の記事で行いましたが、 今回はこれを複数のクライアントとの通信が出来る様に変更してみました。
⇒名前付きパイプを使ったプロセス間通信について
変更個所は、通信開始の時にサーバー処理のスレッドを複数立ち上げて、別々のクライアントからの受信をそれぞれのスレッドで受ける様にします。 サーバースレッドの終わりでは、スレッドの終了をスレッドの個数分終わった時点で、再度の通信開始のボタンを押下出来る様にしています。
今回のサーバースレッドの起動数は3個に抑えてありますし、スレッドの終了判定などが適当ですので改良の余地はありますが。
サーバー側プログラム
Imports System.Threading
Imports System.IO
Imports System.IO.Pipes
Public Class frmNameServer
'別スレッドからメッセージを処理するためデリゲートを利用
Delegate Sub SetRichTextBox1Delegate(ByVal Value As String)
Private RichTextBox1Delegate As New SetRichTextBox1Delegate(AddressOf _
AppendTextRichTextBox1)
'リッチテキストボックスにメッセージを表示する
Private Sub AppendTextRichTextBox1(ByVal message As String)
RichTextBox1.AppendText(message)
RichTextBox1.SelectionStart = RichTextBox1.TextLength
End Sub
'別スレッドからボタンの許可設定処理するためデリゲートを利用
Delegate Sub SetButton1EnabledDelegate(ByVal bln As Boolean)
Private SetButton1Delegate As New SetButton1EnabledDelegate(AddressOf _
SetButton1Enabled)
'[Buttin1]のEnabled設定
Private Sub SetButton1Enabled(ByVal blnEnabled As Boolean)
Me.Button1.Enabled = blnEnabled
End Sub
'サーバスレッドの数
Private Const numThreads As Integer = 3
'サーバスレッド配列
Private arrServer(numThreads - 1) As Thread
'サーバスレッド終了フラグ件数
Private intServerFinish As Integer = 0
'[Start NamePipe]ボタンクリックイベント
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
intServerFinish = 0
'名前付きパイプによる通信スレッド開始
For i = 0 To UBound(arrServer)
arrServer(i) = New Thread(AddressOf ServerThread)
arrServer(i).Start()
Next
AppendTextRichTextBox1("名前付きパイプ通信待機中・・・" & vbNewLine)
'[Start NamePipe]ボタン不可設定
Me.Button1.Enabled = False
End Sub
'名前付きパイプによる通信スレッド
Private Sub ServerThread()
'サーバー用のパイプを双方向でクライアント数は指定値で生成
Dim pipeServer As New NamedPipeServerStream("PIPE_TEST", PipeDirection.InOut, numThreads)
Try
'パイプスレッド取得
Dim threadId As Integer = Thread.CurrentThread.ManagedThreadId
Me.Invoke(RichTextBox1Delegate, _
New Object() {"パイプ生成完了(スレッドID:" & threadId & ")" & vbNewLine})
'パイプの接続を待つ
pipeServer.WaitForConnection()
Me.Invoke(RichTextBox1Delegate, New Object() {"パイプ接続完了(スレッドID:" & threadId & ")" & vbNewLine})
'ストリーム読込を生成
Dim pipeStreamReader As New StreamReader(pipeServer)
Try
While True
'パイプからの文字列受信(入力)
Dim strRead As String = pipeStreamReader.ReadLine()
'ストリームの末尾に到達した場合はNullなので、通信を終了する
'If strRead Is Nothing Then
If strRead = "" Then
Exit While
End If
'受信文字列の表示
Me.Invoke(RichTextBox1Delegate, New Object() {"受信文字列(スレッドID:" & threadId & "):" & strRead & vbNewLine})
End While
Catch ex As IOException
MsgBox(ex.Message)
Finally
pipeStreamReader.Close()
End Try
'invokeTextBox(dlg, "パイプ通信を終了します。")
Me.Invoke(RichTextBox1Delegate, New Object() {"パイプ通信の終了" & vbNewLine})
intServerFinish += 1
If intServerFinish >= numThreads Then
'[Button1]の許可設定
Me.Invoke(SetButton1Delegate, New Object() {True})
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
pipeServer.Close()
End Try
End Sub
End Class
クライアント側プログラムは「名前付きパイプを使ったプロセス間通信について」のものと変わっていません。
クライアント側プログラム
Imports System.IO
Imports System.IO.Pipes
Imports System.Security.Principal
Public Class frmNameClient
'[Start Named Pipe]ボタンクリック時イベント
Private Sub ButtonSend_Click(sender As Object, e As EventArgs) _
Handles ButtonSend.Click
Dim pipeStream As NamedPipeClientStream = Nothing
Dim pipeSw As StreamWriter = Nothing
Try
'[Send Message]ボタンを不可設定
Me.ButtonSend.Enabled = False
'名前付きパイプ・クライアント生成
pipeStream = New NamedPipeClientStream(".", "PIPE_TEST", _
PipeDirection.InOut, _
PipeOptions.None, _
TokenImpersonationLevel.Impersonation)
'名前付きパイプ接続
pipeStream.Connect(1000)
'ストリームライタ
pipeSw = New StreamWriter(pipeStream)
pipeSw.AutoFlush = True
'文字列送信
pipeSw.WriteLine(Me.TextBox1.Text.Trim)
Catch ex As Exception
MsgBox(ex.Message)
Finally
'ストリームライタを閉じる
If Not pipeSw Is Nothing Then
pipeSw.Close()
End If
'名前付きパイプを閉じる
If Not pipeStream Is Nothing Then
pipeStream.Close()
End If
'[Send Message]ボタンを許可設定
Me.ButtonSend.Enabled = True
End Try
End Sub
End Class
サーバー側のEXEを実行した後、クライアントEXEを3個実行します。 その後、サーバー側の「Start NamePipe」ボタンを押下して、各クライアントの「Start Name Pipe」ボタンを順次押下します。 各クライアント側で送信文字列を入力して「Send Message」ボタンを押下した結果の画像です。
尚、以下は各クライアント側で送信文字列をクリアして「Send Message」ボタンを押下して一連の処理を終了した結果の画像です。
関連する記事
⇒Remoting の IPC を使ったプロセス間通信について⇒Remoting の IPC を使ったプロセス間通信についてその2(HTTPチャネル)
⇒名前付きパイプを使ったプロセス間通信について
⇒名前付きパイプを使ったプロセス間通信についてその3(クライアントとの双方向通信)
PR
コメント