Невозможно получить данные асинхронно от UDPClient после отправки, в VB.Net - PullRequest
0 голосов
/ 04 февраля 2019

Я хочу написать некоторый код VB.NET, который отправляет несколько байтов в Broadcast и получает ответ от различных устройств, которые неизвестны при отправке: известно только номер порта для отправки широковещания, порт, который прослушивают эти устройства.

Единственный способ, которым я могу сделать эту работу на данный момент, - это синхронный способ (точнее, с асинхронными вызовами методов и синхронным ожиданием ответа, поэтому это синхронный путь), и это проблема, потому что мое приложениепри этом блокируется.

Вот код, который действительно работает:

        broadcastIPEP = New IPEndPoint(IPBroadcast_, port_)
        'Create Broadcaster
        UDPClient = New UdpClient With {.EnableBroadcast = True}
        'Send array of bytes 
        nbBytesSent = UDPClient.Send(bytTab, bytTab.Length, broadcastIPEP.Address.ToString, broadcastIPEP.Port)
        'Get the number of the port to listen
        port = DirectCast(UDPClient.Client.LocalEndPoint, IPEndPoint).Port
        'Close broadcaster
        UDPClient.Close()
        'Create new listener on port
        UDPClient = New UdpClient(port)
        While True
            nbMsWait = 0I
            'Start receive
            ar = UDPClient.BeginReceive(Nothing, Nothing)
            'Wait answer until it comes
            Do
                nbMsWait += DELAY_WAIT_RESPONSE
                If nbMsWait > DELAY_MAX_WAIT_RESPONSE Then
                    Exit Try
                End If
                ar.AsyncWaitHandle.WaitOne(DELAY_WAIT_RESPONSE)
            Loop Until ar.IsCompleted
            'Read answer
            bytTab = UDPClient.EndReceive(ar, ipRemote)
            strMsg = Text.Encoding.UTF8.GetString(bytTab)
            'Process received message
            ProcessResponse(strMsg)
        End While

Он работает нормально, но, как я уже сказал, проблема в том, что он действительно не асинхронный.Все мои попытки заставить его работать асинхронным способом не работают, потому что данные никогда не поступают в мой UDPClient, когда я делаю это асинхронно.И я пробовал много способов: используя асинхронные методы чисто асинхронным способом, что-то вроде этого:

broadcaster = New UdpClient With {.EnableBroadcast = True}
broadcaster.BeginSend(BYTES_TO_SEND, NB_BYTES_TO_SEND, broadcastIPEP, New AsyncCallback(AddressOf OnDataSent), broadcaster)

Вот обратный вызов отправки

Protected Sub OnDataSent(ar As IAsyncResult)

    'Local variables
    Dim broadcaster As UdpClient = Nothing, client As UdpClient = Nothing
    Dim port As Integer = 0I

    Try
        broadcaster = DirectCast(ar.AsyncState, UdpClient)
        port = DirectCast(broadcaster.Client.LocalEndPoint, IPEndPoint).Port
        broadcaster.Close()
        client = New UdpClient(port)
        'Schedule the next receive operation once reading is done:
        client.BeginReceive(New AsyncCallback(AddressOf OnDataReceived), client)
    Catch ex As Exception
        ProcessError(ex)
    End Try

End Sub

А вот обратный вызов приема:

Protected Sub OnDataReceived(ar As IAsyncResult)

    'Local variables
    Dim client As UdpClient = Nothing
    Dim source As IPEndPoint = Nothing
    Dim bytTab() As Byte = Nothing
    Dim strMsg As String = String.Empty

    Try
        'This is what had been passed into BeginReceive as the second parameter:
        client = DirectCast(ar.AsyncState, UdpClient)
        'Points towards whoever had sent the message:
        source = New IPEndPoint(0, 0)
        'Get the actual message and fill out the source:
        bytTab = client.EndReceive(ar, source)
        'Process received message
        strMsg = Encoding.GetString(bytTab)
        ProcessResponse(strMsg)
        'Schedule the next receive operation once reading is done:
        client.BeginReceive(New AsyncCallback(AddressOf OnDataReceived), client)
    Catch ex As Exception
        ProcessError(ex)
    End Try

End Sub

Выполнение входит в отправку обратного вызова, но никогда в обратный вызов приема.

Я пытался использовать синхронный метод в отдельном потоке, но та же проблема: невозможно получить что-либо, иЯ уверен, что есть что получить.Вот код подпрограммы потока:

    'Local Variables
    Dim nbBytes As Integer = 0I
    Dim bytTab() As Byte = Nothing
    Dim strMsg As String = String.Empty

    Try
        'Get broadcast address
        broadcastIPEP = DirectCast(IP_, IPEndPoint)
        'Create broadcaster
        UDPBroadcaster = New UdpClient With {.EnableBroadcast = True}
        'Set broadcast address to broadcaster
        UDPBroadcaster.Connect(broadcastIPEP)
        'Send broadcast
        nbBytes = UDPBroadcaster.Send(BYTES_TO_SEND, NB_BYTES_TO_SEND)
        'Get the port to listen
        listenPort = DirectCast(UDPBroadcaster.Client.LocalEndPoint, IPEndPoint).Port
        'Close broadcaster
        UDPBroadcaster.Close()
        'Create listener
        UDPListener = New UdpClient(listenPort)
        'Create listening address
        listenIPEP = New IPEndPoint(IPAddress.Any, listenPort)
        'listening loop
        While booListen
            Thread.Sleep(10I)
            If booNotify Then
                Continue While
            End If
            bytTab = UDPListener.Receive(listenIPEP)
            strMsg = Text.Encoding.UTF8.GetString(bytTab)
            ProcessResponseAsync(strMsg)
        End While
    Catch ex As Exception
        ProcessError(ex)
    End Try

Может кто-нибудь сказать мне, почему невозможно получить асинхронный прием с UDPClient?Спасибо всем, кто поможет

...