Не получать данные из сокета, когда данные должны быть там, и никаких исключений не возникает, соединение открыто. Использование DataAvailable для ожидания данных

У меня проблема со считыванием данных с RFID-считывателя. Я подключаюсь к считывателю по tcp и жду, пока DataAvailable будет истинным, затем читаю данные, пока не получу символ конца данных. Затем я просто возвращаюсь и жду нового DataAvailable. Это делается в собственном потоке для функции.

Кажется, есть какой-то тайм-аут. Если я не получу никаких данных через пару минут, то они просто будут сидеть в цикле выполнения/цикла, ожидая DataAvailable. Подношу карту к считывателю RFID, он пищит, но данных нет. Я не получаю никаких исключений, и в информации говорится, что clientsocket все еще подключен. Есть ли что-нибудь еще, что я могу проверить?

Если я поднесу карту к считывателю через минуту, то этого, кажется, никогда не произойдет. Таким образом, 2-3 минуты простоя, кажется, делают это.

Вот мой код для чтения данных из сокета, я убрал ненужный код:

Sub test(ByVal ip As String, ByVal port As Integer)
    ' this sub is meant to run forever
    Try
        Dim clientSocket As New System.Net.Sockets.TcpClient()
        clientSocket.Connect(ip, port)
        Using serverStream As NetworkStream = clientSocket.GetStream()
            Do 'loop forever or until error occur

                'Every new dataentry starts here
                Dim inStream(0) As Byte
                Dim returndata As String = ""

                Do 'loop forever 
                    Do Until serverStream.DataAvailable 'loop until data exists to read
                        If clientSocket.Connected = False Then

                            'this will never happen.
                            'but if there are more than 5 minutes between data then
                            'it never got data again as if no data was sent.

                            Exit Sub
                        End If
                        Application.DoEvents()
                    Loop

                    'there is data to read, read first byte and 
                    serverStream.Read(inStream, 0, 1)
                    If inStream(0) = 13 Then

                        'got end of data
                        'exit loop if reading chr 13.
                        returndata &= System.Text.Encoding.ASCII.GetString(inStream)
                        Exit Do

                    End If
                Loop

                GotData(returndata)

            Loop
        End Using
    Catch ex As Exception
        ' handle error
    Finally
        'close connection if open
    End Try
End Sub

person Stefan    schedule 24.03.2011    source источник
comment
Я не думаю, что это решит вашу проблему, но я бы рекомендовал добавить туда Thread.Sleep(int) перед закрытием внешнего цикла. Возможно, установите его для 100 или 250. В противном случае вы вращаетесь по очень узкому кругу, тратя впустую циклы процессора. Этот внешний цикл может фактически работать со скоростью сотни в миллисекунду.   -  person Chris Haas    schedule 24.03.2011
comment
@Chris, спасибо, похоже, что мой application.doevents возвращает циклы процессора ОС, большую часть времени программа работает внутри цикла ожидания данных, так что я поставил это там. Но, возможно, мне следует заменить это на thread.sleep.   -  person Stefan    schedule 24.03.2011


Ответы (1)


Я обнаружил, что socket.Connected отчитывается только о состоянии, когда последняя команда была запущена для соединения. Итак, в цикле Do until serverStream.DataAvailable я использовал этот трюк, чтобы проверить, было ли закрыто соединение:

Dim test As Boolean = clientSocket.Client.Poll(10, System.Net.Sockets.SelectMode.SelectRead)
If test = True And serverStream.DataAvailable = False Then
   'restart connection
End If

Итак, теперь, наконец, я получил контроль над тем, что происходит, и знаю, что из-за того, что клиентское соединение закрыто, я не получил никаких данных.

Итак, я подумал, теперь, когда я знаю, что соединение закрыто, как мне это предотвратить? Это было проще, просто отправляйте данные на tcpip-сервер каждые 10 секунд, и он будет держать его открытым.

Результат, который у меня работает (это не рабочий код, просто пример решения):

    Dim s As Date = Now
    Do Until serverStream.DataAvailable
        Dim r As Boolean = clientSocket.Client.Poll(10, System.Net.Sockets.SelectMode.SelectRead)
        If DateDiff(DateInterval.Second, s, Now) > 10 Then
           Dim dta(0) As Byte
           dta(0) = 0
           clientSocket.Client.Send(dta)
           s = Now
        End If
        If r = True And serverStream.DataAvailable = False Then
             'restart sub
             Exit Sub
        End If
   loop

Так что теперь он даже не закрывается и должен перезапускаться каждые x минут.

Мои проблемы решены, и я счастливый кодер. ;)

person Stefan    schedule 24.03.2011
comment
хорошо. когда выполняется запрос, мы ожидаем текущее состояние, а не предыдущее, поэтому этот опрос должен был быть встроенным, это источник путаницы. - person kobi7; 11.08.2011