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

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

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

Re[3]: VB.NET_SOCKET通信で受信イベントが発生しなくなる


(過去ログ 177 を表示中)

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

■101690 / inTopicNo.1)  VB.NET_SOCKET通信で受信イベントが発生しなくなる
  
□投稿者/ KAZUMA (1回)-(2023/03/31(Fri) 20:44:03)

分類:[.NET 全般] 

vb net netframework4.6.1 vs2019

ある検査機器と、TCP通信でデータを受け取るプログラムを作ったいるのですが、
最初のデータは受け取れるのですが、数十分後に送られてくるデータに
OnConnectRequestが発生しなくなります。

検査機器は、常時接続でコネクションはつながったままです。
wiresharkのパケットキャプチャでログを記録したのですが、
最初のデータ(ENQからEOTまで)を受け取ってから、数十分ごの次のデータ(ENQ)を
検査機器がENQを送信しつづけているのですが、
ENQを受け取ったときに、発生するOnConnectRequestが発生せしないため
ACKを返せず、検査機器はENQを送り続けてしまいます。

・常時接続に対して、下記の組み方はあっているのでしょうか?
・パケットキャプチャでは受け取っているENQが、動作しているEXEが受け取れとれていないとすると、
 なにが原因が考えられるでしょうか

なにか、これ調べたらというヒントだけでも頂けたましたら、ありがたいです。







    Public Sub New(ByVal ip As String, ByVal port As String, ByVal _mekTable As tableMEK)

        frmMain.WriteLog("Program ThreadID:" & Thread.CurrentThread.ManagedThreadId)

        Dim myIP As IPAddress = IPAddress.Parse(ip)

        ipEndPoint = New IPEndPoint(myIP, Int32.Parse(port))

        frame = New Frame

        mekTable = _mekTable

        listFrameEditer = New List(Of FrameEditer)

        dataFrameIndex = 1

    End Sub

    Public Overloads Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
    End Sub


    Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
        If Not _disposed Then
            If disposing Then
                '*** アンマネージリソースの開放
                frmMain.WriteLog("process end")
                threadMain.Abort()

            End If
            '*** マネージドリソースの開放

        End If
        _disposed = True
    End Sub


    Public Sub Initialize()

        frmMain.WriteLog("init ThreadID:" & Thread.CurrentThread.ManagedThreadId)

        sock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True) 'http://blog.livedoor.jp/nanoris/archives/51820671.html こうしないと同じポートを再度使えない

        sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, True)


        Dim keepAliveTime As UInteger = 60000  '待ち時間 30秒 
        Dim keepaliveinterval As UInteger = 2000 '間隔
        SetKeepAlive(sock, keepalivetime, keepaliveinterval)

        sock.Bind(ipEndPoint)
        sock.Listen(10)

        frmMain.WriteLog("サーバー起動中・・・")

        threadMain = New Thread(New ThreadStart(AddressOf Round))
        threadMain.Start()

    End Sub

    ''' <summary>
    ''' TCP KEEPALIVE
    ''' 参考:https://stackoverflow.com/questions/10292593/how-to-implement-tcp-keepalive-in-vb-net-on-a-tcp-clientsocket
    ''' </summary>
    ''' <param name="tcpSocket"></param>
    ''' <param name="keepAliveTime"></param>
    ''' <param name="keepAliveInterval"></param>
    ''' <returns></returns>
    Private Shared Function SetKeepAlive(ByRef tcpSocket As Socket, ByVal keepAliveTime As UInteger, ByVal keepAliveInterval As UInteger) As Boolean
        ' Pack three params into 12-element byte array; not sure about endian issues on non-Intel
        Dim SIO_KEEPALIVE_VALS(11) As Byte
        Dim keepAliveEnable As UInteger = 1
        If (keepAliveTime = 0 Or keepAliveInterval = 0) Then keepAliveEnable = 0
        ' Bytes 00-03 are 'enable' where '1' is true, '0' is false
        ' Bytes 04-07 are 'time' in milliseconds
        ' Bytes 08-12 are 'interval' in milliseconds
        Array.Copy(BitConverter.GetBytes(keepAliveEnable), 0, SIO_KEEPALIVE_VALS, 0, 4)
        Array.Copy(BitConverter.GetBytes(keepAliveTime), 0, SIO_KEEPALIVE_VALS, 4, 4)
        Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, SIO_KEEPALIVE_VALS, 8, 4)

        Try
            Dim result() As Byte = BitConverter.GetBytes(CUInt(0)) ' Result needs 4-element byte array?
            tcpSocket.IOControl(IOControlCode.KeepAliveValues, SIO_KEEPALIVE_VALS, result)
        Catch e As Exception
            Return False
        End Try
        Return True
    End Function

    Private Sub Round()

        frmMain.WriteLog("Round ThreadID:" & Thread.CurrentThread.ManagedThreadId)

        hasOpen = True

        While True

            SocketEvent.Reset()
            sock.BeginAccept(New AsyncCallback(AddressOf OnConnectRequest), sock)
            SocketEvent.WaitOne()

        End While

    End Sub

    ''' <summary>
    ''' クライアント接続時処理
    ''' affinionは接続し続ける
    ''' </summary>
    ''' <param name="ar"></param>
    Private Sub OnConnectRequest(ByVal ar As IAsyncResult)

        frmMain.WriteLog("OnConnectRequest ThreadID:" & Thread.CurrentThread.ManagedThreadId)
        SocketEvent.[Set]()

        Dim listener As Socket = CType(ar.AsyncState, Socket)
        Dim handler As Socket = listener.EndAccept(ar)

        frmMain.WriteLog(handler.RemoteEndPoint.ToString() & " joined")

        Dim state As StateObject = New StateObject()

        state.workSocket = handler
        handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, New AsyncCallback(AddressOf ReadCallback), state)

        'データリスト初期化
        listData = New List(Of String)
        'データ編集を初期化
        receivedFrameEditer = New FrameEditer(Me.mekTable)
        'コマンドバッファクリア
        Me.CmdBuf = Nothing

        '*** データ受信イベントを発生 ***
        Dim se As New TcpEventArgs
        se.ReceivedData = "CON->" & handler.RemoteEndPoint.ToString() & " joined"
        RaiseEvent ReceivedData(Me, se)

    End Sub

引用返信 編集キー/
■101693 / inTopicNo.2)  Re[1]: VB.NET_SOCKET通信で受信イベントが発生しなくなる
□投稿者/ KOZ (398回)-(2023/04/03(Mon) 11:03:05)
No101690 (KAZUMA さん) に返信
> ・常時接続に対して、下記の組み方はあっているのでしょうか?
> ・パケットキャプチャでは受け取っているENQが、動作しているEXEが受け取れとれていないとすると、
>  なにが原因が考えられるでしょうか
> なにか、これ調べたらというヒントだけでも頂けたましたら、ありがたいです。

コードの一部だけでは原因を特定できませんし、アドバイスもしにくいです。
現象が発生する最低限のコードを提示してください。
コードを整理しているうちに原因が判明することもあります。

とりあえず、気になった箇所は以下の2点。

(1) Listen する Socket に ReuseAddress オプションは不要です。何か理由がありますか?
(2) キープアライブ設定は EndAccept で得られた Socket に設定しなければ無意味では?


引用返信 編集キー/
■101694 / inTopicNo.3)  Re[2]: VB.NET_SOCKET通信で受信イベントが発生しなくなる
□投稿者/ KOZ (399回)-(2023/04/03(Mon) 12:08:00)
No101693 (KOZ) に返信

もう一点。
MSDN のサンプルには、BeginAccept をメインループで実行し、コールバックからイベント通知する例が載っており、似た作りになっていますが
Listen 時のバックログ数に余裕をもたせておけば、EndAccept 後に BeginAccept を実行して良い気がします。

引用返信 編集キー/
■101696 / inTopicNo.4)  Re[3]: VB.NET_SOCKET通信で受信イベントが発生しなくなる
□投稿者/ Hongliang (1285回)-(2023/04/03(Mon) 12:44:37)
そもそもの話、接続しっぱなしなのであれば、接続は最初の1回だけしか発生しないのだから、OnConnectRequestが1回しか呼び出されないのは当然では?
接続後は受信(Receive系メソッド)を何度も繰り返し呼び出す形になるかと思います。そっちの方の記載はないので具体的な助言はできませんが。
引用返信 編集キー/


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -