C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

TCP通信でのサブスレッドの終了

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■82873 / inTopicNo.1)  TCP通信でのサブスレッドの終了
  
□投稿者/ あぼん (1回)-(2017/02/16(Thu) 22:17:20)

分類:[ASP.NET (VB)] 

.NET Framework4.5
言語:Visual Basic
Windowsフォームアプリケーション

とあるサイトのサンプルからTCP通信のフォームアプリケーションを作ろる為に勉強しています。
そのサイトのサンプルではサーバー側とクライアント側をラジオボタンによって切り分けています。
私はそれをサーバー側とクライアント側に分けて、二つのフォームアプリケーションを作ろうとしています。
ほとんどサンプルを流用しているので、TCP通信のところは問題なく繋がったのですが、
サーバー側のアプリケーションでクライアントからの接続を待機中のスレッドを終了させようとするとフリーズしてしまいます。
サンプルでは特に問題なく終了できるのになぜ私の方では固まるのかがわかりません。
スレッドやTCP通信等に触れるのも初めてのことであり、何か根本的に理解できていない部分もあるのではないかと思い、質問させて頂きました。

また、サブスレッドをAbortで終了させるのもあまりよくないと聞きます。
接続待機中のスレッドを終了させる方法が何かありましたら、そちらもお聞きしたいと思います。
どうぞ、よろしくお願いします。

↓サーバー側の問題箇所の部分を書いたものです。

Imports System.Net.Sockets
Imports System.Threading

Public Class Form1
    'サーバー設定
    Dim server As TcpClient = Nothing
    'サーバーのリスナー設定
    Dim listener As TcpListener = Nothing
    'サーバーのセカンドスレッドの設定
    Dim threadServer As Thread = Nothing

    'デリゲート宣言
    '別スレッドからメインスレッドのテキストボックスに書き込むデリゲート
    Delegate Sub dlgWriteText(ByVal text As String)

    '引数を持たない汎用のデリゲート
    'ストップボタンを押す等に使用
    Delegate Sub dlgMydelegate()

    'ソケット通信の開始処理
    'Startボタン押下
    Private Sub StartServerbtn_Click(sender As Object, e As EventArgs) Handles StartServerbtn.Click
        StartSock()
    End Sub

    'ソケット通信開始
    Private Sub StartSock()
        'サーバースタート
        Dim OpenFlg As Boolean

            OpenFlg = ServerStart()
            picIndicator.BackColor = Color.Green

        'ボタンのenableを変える
        If OpenFlg Then
            StartServerbtn.Enabled = False
            StopServerbtn.Enabled = True
        End If
    End Sub


    'セカンドスレッドの作成とサーバーのスタート
    Private Function ServerStart() As Boolean

        'ListenするIPアドレス
        Dim ipString As String
        Dim ipAdd As System.Net.IPAddress

        'Listenするポート番号
        Dim port As Integer

        'サーバーのIPアドレス(または、ホスト名)とポート番号をテキストボックスから取得
        ipString = textBoxIp.Text
        ipAdd = System.Net.IPAddress.Parse(ipString)
        port = Integer.Parse(textBoxPortNo.Text)

        'TcpListenerを使用してサーバーの接続の確立
        Try

            'lisenerが無い場合
            If listener Is Nothing Then
                listener = New TcpListener(ipAdd, port)
            End If
            'クライアント接続要求の受付開始
            listener.Start()


            'スレッドの作成と開始
            threadServer = New Thread(New ThreadStart(AddressOf ServerListen))
            threadServer.Start()
            Return True

        Catch ex As Exception
            'エラーが起きた
            listener.Stop()
            picIndicator.BackColor = Color.Navy
            Return False
        End Try
    End Function

    Private Sub ServerListen()

        'クライアントの要求があったら、接続を確立する
        'クライアントの要求が有るまでここで待機する 
        server = listener.AcceptTcpClient()

        'インジケータの色を変える
        'バックカラーの変更はデリゲートの必要は無し
        picIndicator.BackColor = Color.LightGreen

        'クライアントとの間の通信に使用するストリームを取得
        Dim stream As NetworkStream = server.GetStream()

        '受信文字が入る。
        'この数字は少なくても可、少ない場合はLoopが何回か実行される
        Dim bytes(1000) As Byte


        '受信が無い場合はここで待機する
        '文字受信が有った場合とクライアントが接続を切った場合に
        '次のステップに進む
        Dim intCount As Integer = stream.Read(bytes, 0, bytes.Length)

    End Sub



    Private Sub StopServerbtn_Click(sender As Object, e As EventArgs) Handles StopServerbtn.Click
        StopSock()
    End Sub

    Private Sub StopSock()
        'サーバーストップ
        CloseServer()

        StartServerbtn.Enabled = True
        StopServerbtn.Enabled = False

    End Sub

    'サーバーのクローズ
    Private Sub CloseServer()
        'サーバーのインスタンスが有って、接続されていたら
        If server IsNot Nothing AndAlso server.Connected Then
            server.Close()
        End If
        Try
            'スレッドは必ず終了させること
            If threadServer IsNot Nothing Then
                threadServer.Abort()
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString())
        End Try

        'インディケータの色を変える            
        picIndicator.BackColor = Color.Navy

    End Sub

End Class

引用返信 編集キー/
■82935 / inTopicNo.2)  Re[1]: TCP通信でのサブスレッドの終了
□投稿者/ リャマ (1回)-(2017/02/20(Mon) 12:41:08)
No82873 (あぼん さん) に返信

スレッドの終了についてググったところこんなの見つけました
http://stackoverflow.com/questions/16214488/how-to-abort-thread-that-use-accepttcpclient-inside
http://stackoverflow.com/questions/12231789/cancel-blocking-accepttcpclient-call

TcpListener.AcceptTcpClient()はTcpListener.Stop()でキャンセルすることができて
TcpListener.Stop()がキャンセルされたときSocketExceptionが投げられるので
SocketExceptionを捕まえてよろしく処理したらいいよってことらしいです

CloseServerでTcpListener.Stop()を呼んでthreadServerが終了するのを待つのがいんじゃないでしょうか
引用返信 編集キー/
■82936 / inTopicNo.3)  Re[2]: TCP通信でのサブスレッドの終了
□投稿者/ リャマ (2回)-(2017/02/20(Mon) 12:42:52)
No82935 (リャマ さん) に返信
> TcpListener.Stop()がキャンセルされたときSocketExceptionが投げられるので

TcpListener.Stop()がキャンセルされたときじゃないですね、意味がわかりませんね
TcpListener.AcceptTcpClient()がキャンセルされたときです
引用返信 編集キー/
■82949 / inTopicNo.4)  Re[3]: TCP通信でのサブスレッドの終了
□投稿者/ あぼん (2回)-(2017/02/20(Mon) 23:32:43)
No82936 (リャマ さん) に返信

リャマ さん返信ありがとうございます!
URLと解説を読んで固まることなく、スレッドを閉じる事ができました。

無事解決する事ができ、本当にありがとうございました!

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ