忍者ブログ

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

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

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

前回の TCP の記事では、クライアント側で1回の通信毎に TCP の接続を切断していたので、 複数回の文字列送信ができませんでした。
それで今回は、クライアント側で TCP の接続のタイミングと、文字列送信のタイミングを別々で行う様にすることで 複数回の文字列送信を可能にしています。

これを行う為に、以下のクライアント側の処理手順の中で、(1)(2)を1個の処理として、また(5)の処理も別のタイミングに追い出します。 具体的にはそれぞれフォームにボタンを設置(「Start」「Stop」の名前で)し、それぞれのクリック処理内でそれらを行います。

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

それでは以下にクライアント側のソースを示します。 TcpClientNetworkStream クラスのオブジェクトを関数の外に出し、静的変数としています。

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

Imports System.Net
Imports System.Text

Public Class frmTcpClient

    'サーバーのIPアドレス(または、ホスト名)とポート番号
    Dim strIpAddr As String = "localhost"
    Dim intPort As Integer = 60000

    'ソケット
    Dim mTcpClient As Sockets.TcpClient
    'ソケットストリーム
    Dim mNetStream As Sockets.NetworkStream

    '[Start]リック時イベント
    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        'ソケット生成
        mTcpClient = New Sockets.TcpClient
        'ソケット接続
        mTcpClient.Connect(strIpAddr, intPort)
        'ソケットストリーム取得
        mNetStream = mTcpClient.GetStream()
    End Sub

    '[Stop]リック時イベント
    Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
        'ソケットクローズ
        mNetStream.Close()
        mTcpClient.Close()
    End Sub

    '[Send]リック時イベント
    Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
        Try
            '送信文字列をバイト配列変換
            Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS")
            '最後尾にCR
            Dim data As Byte() = enc.GetBytes(Me.TextBox1.Text.Trim & ControlChars.Cr)
            Me.TextBox1.Text = ""

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

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

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

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

End Class

サーバ側のプログラムに変更は無いのですが、一応ソースを載せておきます。

■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

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

サーバ側の「Start」押下後、クライアント側の「Start」を押下し”abcdef”,”123456”,”ABCDEFGHI”の順に文字列を「Send」し、 更に「Stop」を押下したところまでを表しています。

ここまでのPGはサーバとクライアントが1対1のみでしか動作しません。 しかし、これでは面白くありませんので、次回は複数のクライアントからの接続を受け付けるものを紹介したいと思います。

関連する記事

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











PR

コメント

コメントを書く