VisualBasicでもソケット通信-マルチスレッドでノンブロッキング動作編

|

前回までの動作は、サーバー側/クライアント側共にブロッキングモードだったので、マルチスレッドを利用してサーバー側の見掛け上のハングアップ(応答なし)を回避してみる事に。

(クライアント側を敢えてスレッド分けする利点が・・・)


<注意点>

・動作はスレッド利用によりノンブロッキングモードです。

・クライアント側ソースの前回との相違は、以下のみ。
    Dim message As String = "There is it!<EOF>"

・エラー処理は手抜きです。


お試し環境
  Windows7 64bit Edition
  Visual Basic 2008 AnyCPU対象


/*---- サーバー側 -------------------- お試し結果 --------------------------*/

Waiting for a connection...
Connected!
Waiting for a connection...
Received: There is it!<EOF>
Sent: THERE IS IT!<EOF>

/*----------------------------------------------------------------------------*/

/*---- クライアント側 ---------------- お試し結果 --------------------------*/

Sent: There is it!<EOF>
Received: THERE IS IT!<EOF>

/*----------------------------------------------------------------------------*/


/*---- サーバー側 ------------------  お試しソース -------------------------*/

'Imports System.Net
'Imports System.Net.Sockets
'Imports System.Text

Public Class Form1

    Private Sub subThread2(ByVal obj As Object)

        Dim clnt As Net.Sockets.TcpClient ' クライアント側ソケットのコピー
        Dim stream As Net.Sockets.NetworkStream ' クライアント側との送受信ストリーム

        ' バイト列送受信バッファ
        Dim sndBytes(1024) As Byte
        Dim rcvBytes(1024) As Byte

        Dim i As Integer
        Dim msg As String

        clnt = CType(obj, Net.Sockets.TcpClient)
        Try
            ' クライアントとの送受信ストリーム取得
            stream = clnt.GetStream()

            ' データを全て受信するまでループ
            i = stream.Read(rcvBytes, 0, rcvBytes.Length)
            While (i <> 0)
                ' 受信バイト列を文字列に変換
                msg = System.Text.Encoding.ASCII.GetString(rcvBytes, 0, i)
                Debug.Print("Received: {0}", msg)

                ' 受信データ処理
                msg = msg.ToUpper()
                sndBytes = System.Text.Encoding.ASCII.GetBytes(msg)

                ' 応答送信
                stream.Write(sndBytes, 0, sndBytes.Length)
                Debug.Print("Sent: {0}", msg)

                i = stream.Read(rcvBytes, 0, rcvBytes.Length)
            End While

            ' クライアント側ソケット解放
            stream.Close()
            clnt.Close()

        Catch ex As Net.Sockets.SocketException
            Debug.Print("SocketException : {0}", ex)
            Throw ' 例外が呼出し元に伝わるかは未確認
        Finally
            clnt.Close()
        End Try

    End Sub

    Private Sub subThread1(ByVal obj As Object)

        Dim srv As Net.Sockets.TcpListener ' リスナー側ソケットのコピー
        Dim client As Net.Sockets.TcpClient ' クライアント側ソケット

        Dim t As Threading.Thread ' スレッド

        srv = CType(obj, Net.Sockets.TcpListener)
        Try
            ' 接続要求受け取り開始
            While True
                Debug.Print("Waiting for a connection... ")

                ' 接続要求許可待ちの間、プログラムは一時停止
                client = srv.AcceptTcpClient()
                Debug.Print("Connected!")

                ' スレッド開始
                t = New Threading.Thread(AddressOf subThread2)
                t.Start(client)

                Threading.Thread.Sleep(0)
            End While

        Catch ex As Net.Sockets.SocketException
            Debug.Print("SocketException : {0}", ex)
        Finally
            srv.Stop()
        End Try

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim server As Net.Sockets.TcpListener ' リスナー側ソケット
        Dim localAddr As Net.IPAddress ' ローカルIPアドレス
        Dim port As Integer

        Dim t As Threading.Thread ' スレッド

        Try
            ' リスナーソケット作成
            port = 22000
            localAddr = Net.IPAddress.Parse("127.0.0.1")
            server = New Net.Sockets.TcpListener(localAddr, port)

            ' クライアントからの受信接続要求リッスン開始
            server.Start()

            ' スレッド開始
            t = New Threading.Thread(AddressOf subThread1)
            t.Start(server)

            Threading.Thread.Sleep(0)

        Catch ex As Net.Sockets.SocketException
            Debug.Print("SocketException : {0}", ex)
        End Try

    End Sub

End Class

/*----------------------------------------------------------------------------*/

/*---- クライアント側 --------------  お試しソース -------------------------*/

'Imports System.Net
'Imports System.Net.Sockets
'Imports System.Text

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim client As Net.Sockets.TcpClient ' クライアントソケット
        Dim port As Integer
        Dim stream As Net.Sockets.NetworkStream ' 送受信ストリーム

        Dim sndData(1024) As Byte ' バイト列送信バッファ
        Dim rcvData(1024) As Byte ' バイト列受信バッファ
        Dim rcvLen As Integer
        Dim msg As String

        Dim server As String = "127.0.0.1"
        Dim message As String = "There is it!<EOF>"

        Try
            ' クライアントソケット作成
            port = 22000
            client = New Net.Sockets.TcpClient(server, port)

            ' 送信文字列をバイト配列に変換
            sndData = System.Text.Encoding.ASCII.GetBytes(message)

            ' 送受信ストリームを取得
            stream = client.GetStream()

            ' サーバーにメッセージ送信
            stream.Write(sndData, 0, sndData.Length)
            Debug.Print("Sent: {0}", message)

            ' 応答データ受信
            rcvLen = stream.Read(rcvData, 0, rcvData.Length)
            msg = System.Text.Encoding.ASCII.GetString(rcvData, 0, rcvLen)
            Debug.Print("Received: {0}", msg)

            ' ソケット解放
            stream.Close()
            client.Close()

        Catch ex As ArgumentNullException
            Debug.Print("ArgumentNullException: {0}", ex)
        Catch ex As Net.Sockets.SocketException
            Debug.Print("SocketException: {0}", ex)
        End Try

    End Sub

End Class

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*============================================================================*/

このブログ記事について

このページは、微禄が2022年1月26日 13:21に書いたブログ記事です。

ひとつ前のブログ記事は「VisualBasicでもソケット通信-TcpListener/TcpClient編」です。

次のブログ記事は「VisualBasicで非同期によるソケット通信、ちょっとその前に」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

お気に入りリンク

NOP法人 アジアチャイルドサポート 最も大切なボランティアは、自分自身が一生懸命に生きること