忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

TCP (TcpListener, TcpClient)を使ったプロセス間通信について

このページでは TCP を使ったプロセス(EXE)間で通信について説明します。 (いわゆる TCP クライアント・サーバプログラム を作ることになります。)

TCP クライアントは TcpClient クラスを、 TCP サーバは TcpListener クラスを使います。
そこで先ずは TCP サーバのプログラムの例を示します。 今回の処理は TCP での受信待ち状態にし、クライアントからの1回のメッセージを受信し、 そのメッセージをクライアント側に返し、処理が終わるという簡単なものです。 以下にその手順を示します。

  • IP アドレスとポート番号でネットワークエンドポイントを作成し TcpListener クラスの生成
  • TcpListener クラスの Start メソッドで受信接続要求の待機を開始
  • TcpListener クラスの AcceptTcpClient メソッドでクライアントからの接続要求を待機
  • 接続要求待機を抜けた後で送受信用ソケットストリーム取得
  • ソケットストリームからデータ受信し、さらにデータを送信
  • 最後にソケットストリーム等をクローズし、リスナーを停止

以下にそのソースを示します。 フォーム上にはサーバ開始用の「start」ボタンと、送受信文字列等を表示する為に RichTextBox を設置しています。

■TCP サーバープログラム

Imports System.Net
Imports System.Threading
Imports System.Text

Public Class frmTcpServer

    'リッチテキストボックスにメッセージを表示する
    Public Sub DispMsg(ByVal message As String)
        RichTextBox1.AppendText(message & vbNewLine)
        RichTextBox1.SelectionStart = RichTextBox1.TextLength
        RichTextBox1.Refresh()
    End Sub

    '[Start]ボタンクリック
    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        'ボタン制御
        Me.btnStart.Enabled = False

        'ポート番号
        Dim pintPort As Integer = 60000
        'IPアドレス&ポート番号設定
        Dim pEndPoint As New IPEndPoint(IPAddress.Any, pintPort)
        'ソケット・リスナー作成
        Dim pListener As New Sockets.TcpListener(pEndPoint)
        'リスナー開始
        pListener.Start()
        Call DispMsg("リスナー開始...")

        'クライアントから接続有りでこの処理を抜ける
        Dim pTcpClient As Sockets.TcpClient = pListener.AcceptTcpClient()
        Call DispMsg("クライアントから接続有り...")

        '送受信用ソケットストリーム取得
        Dim pNetStream As Sockets.NetworkStream = pTcpClient.GetStream()

        'バイト配列(取敢えず受信バッファとして256バイト)
        Dim bytRead As Byte() = New Byte(255) {}

        'ソケット受送信ループ
        While True
            'TCP受信(バッファ領域まで)
            Dim intBytes As Integer = pNetStream.Read(bytRead, 0, bytRead.Count)
            If intBytes = 0 Then
                Exit While
            End If

            '受信したデータを文字列に変換
            Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS")
            Dim resMsg As String = enc.GetString(bytRead, 0, intBytes)
            '末尾の\rを削除
            resMsg = resMsg.TrimEnd(ControlChars.Cr)
            '表示
            Call DispMsg(resMsg)

            '正常受信の場合、送信データ作成
            Dim bytSend() As Byte = enc.GetBytes(resMsg & "...ACK" & ControlChars.Cr)
            'ソケット送信
            pNetStream.Write(bytSend, 0, bytSend.Length)
        End While

        'ソケットストリームクローズ
        pNetStream.Close()
        'クライアントクローズ
        pTcpClient.Close()
        'リスナー停止
        pListener.Stop()
        Call DispMsg("リスナー停止...")

        'ボタン制御
        Me.btnStart.Enabled = True
    End Sub

End Class

以下に TCP クライアントのプログラムの例を示します。 この処理は、TCPソケットを作成・接続した後で、NetworkStream によりサーバへデータを送信し、 その後サーバからの応答を受信します。

  • IP アドレスとポート番号で TcpClient クラスの生成によりTCPソケット作成・接続
  • TcpClient クラスの GetStream メソッドで NetworkStream を取得
  • NetworkStreamWrite メソッドでテキストボックスの内容をバイト配列化して送信
  • NetworkStreamRead メソッドでサーバからの応答を受信しテキストボックスに表示
  • 最後にネットワークストリーム、ソケットをクローズ

以下にそのソースを示します。 フォーム上には送信文字列用と受信文字列用のテキストボックス、送信開始用の「Send」ボタンを設置しています。

■TCP クライアントプログラム

Imports System.Net
Imports System.Text

Public Class frmTcpClient

    '[Send]リック時イベント
    Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
        Me.btnSend.Enabled = False
        Try
            'サーバーのIPアドレス(または、ホスト名)とポート番号
            Dim strIpAddr As String = "localhost"
            Dim intPort As Integer = 60000

            'ソケット生成・指定したホストの指定したポートに接続
            Dim pTcpClient = New Sockets.TcpClient(strIpAddr, intPort)
            'ソケットストリーム取得
            Dim pNetStream As Sockets.NetworkStream = pTcpClient.GetStream()

            '送信文字列をバイト配列変換
            Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS")
            '最後尾にCR
            Dim data As Byte() = enc.GetBytes(Me.TextBox1.Text.Trim & ControlChars.Cr)
            Me.TextBox1.Text = ""

            'ソケット送信
            pNetStream.Write(data, 0, data.Count)

            'サーバからの応答を受信
            Dim bytRead As Byte() = New Byte(255) {}
            Dim intBytes As Integer = pNetStream.Read(bytRead, 0, bytRead.Length)

            '受信したデータを文字列に変換
            Dim resMsg As String = enc.GetString(bytRead, 0, intBytes)
            '末尾の\rを削除し表示
            Me.TextBox2.Text = resMsg.TrimEnd(ControlChars.Cr)

            'ソケットクローズ
            pNetStream.Close()
            pTcpClient.Close()

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Me.btnSend.Enabled = True
    End Sub

End Class

実際の実行は以下の様になります。

今回のPGはクライアント側で文字列送信後すぐに接続を切っていますので、 1回の送受信毎にサーバ側で「start」をクリックしないといけないので実用には供しないですが、ご参考になればと思います。

次回はこれを踏まえて、サーバ側で開始したらそのまま連続でクライアントからの受信と送信を出来る様にしたいと思います。

関連する記事

TCP (TcpListener, TcpClient)を使ったプロセス間通信について・その2
Remoting の IPC を使ったプロセス間通信について
Remoting の IPC を使ったプロセス間通信についてその2(HTTPチャネル)
名前付きパイプを使ったプロセス間通信について
名前付きパイプを使ったプロセス間通信についてその2(複数クライアントとの通信)
名前付きパイプを使ったプロセス間通信についてその3(クライアントとの双方向通信)











PR

コメント

コメントを書く