VB6 Асинхронный клиент Tcp усекает входящие сообщения - PullRequest
2 голосов
/ 23 декабря 2011

У меня есть сервер C # Tcp, который отправляет сообщения зарегистрированным клиентам VB6 Tcp.Получение сообщения осуществляется с помощью WinSock в асинхронном режиме.Таким образом, часть VB6, в которую входит «завершенное» сообщение, выглядит следующим образом:

Private Sub wskConnect_DataArrival(ByVal bytesTotal As Long)
   Dim sBuff As String
   wskConnect.GetData sBuff, vbString       '-- Retrieve sent value
   ProcessMessage sBuff                     '-- Process the value
End Sub

Проблема в том, что Tcp-сервер C # отправляет строку длиной 6874, но когда мы проверяем размер сообщениякак получено, когда происходит событие DataArrival, оно измеряет только 2920. Таким образом, очевидно, что это усечение входящего сообщения является серьезной проблемой.

Кто-нибудь наблюдал это раньше?

Ответы [ 2 ]

8 голосов
/ 23 декабря 2011

Как я уже сказал здесь VB6 WinSock TCP-клиент и .NET TCP-сервер :

Это распространенное заблуждение, что вы получаете сообщения.Вы получаете поток байтов.sBuff может содержать 1 байт, он может содержать 50% того, что составляет ваше сообщение, часто (если они достаточно малы) он может содержать 100% вашего сообщения, а иногда он может содержать более 100% (что означает, что он имеет некоторую частьследующего сообщения).Не видя код в ProcessMessage, я не могу быть уверен, что у вас есть проблема, но вы должны убедиться, что метод может обрабатывать все эти сценарии

Только потому, что вы видите только длину данных 2920 в DataArrivalне означает, что данные были усечены.Это просто означает, что это было все, что было доступно в тот момент.Считайте эти данные в буфер, и затем, когда станет доступна следующая часть отправленных вами данных, событие снова сработает.Продолжайте читать доступные данные и добавляйте их в свой буфер, пока не получите полное сообщение.

1 голос
/ 27 декабря 2011

С контролем mscomm существует та же проблема.Работать с асинхронными событиями всегда сложно.

Во-первых, мой личный способ справиться с этим, вероятно, существует иным способом.так что это еще один вариант.

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

Сначала идея

create time of expiration when it became to be reached 
the information should be complete

ну, нам нужно понять, как происходят события

Графическое представление, которое будет мертвым временем, мертвым временемпросто это период времени

Dead Time view

Теперь в vb6, когда происходят асинхронные события, также должны происходить два действия в разные моменты времени, но они проверяются в один и тот же момент

Action #1 that action update the current time 

Recurrent time

Actions #2 that is limited to update the time current time for async event

update time for async event

Both event are combined on one infinity loop method
the purpose is check current time against the current time of async event

verification for both counter times

Также нам понадобится некоторая утилита для отслеживания времени, когда я использовал выигрышapi GetTickCount

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

Также этот код может вызвать событие itдля повторного использования и изоляции

теперь посмотрите скелет класса vb6

class Module SocketReceptorVb6

   Private Declare Function GetTickCount Lib "kernel32" () As Long   ' API tick

   withevents _tcpControll as Winsock

   private m_currentState As Eventstate  'is a enumerate Waiting, Receiving
   private m_currentTimeAsynEvent As Long  ' current time for async event
   private m_buffer As String
   private m_timeOut as Long

   Public Event StreamReceived(ByVal stream As String) 'Event completed

   Property TimeOut

   private sub Class_Initialize() 
     m_currentState = Waiting
   end sub

   sub tcpControl_DataArrival(bytesTotal)          

   sub Receiving

   sub InitFlags       

End Class

хорошо, теперь давайте посмотрим на 3 метода более внимательно

InitFlags Method

Это очищает переменные и подготавливаетambient, смотрите содержание

m_currentState = Waiting //state of the process
m_buffer = vbNullString  //reset the buffer used for the information

tcpControl_DataArrival Method

Этот методиметь следующие обязанности

   -update buffer 
   -initialize infinity loop 
   -update m_currentTimeAsynEvent

содержание метода

Dim sBuff As String
wskConnect.GetData sBuff, vbString

m_buffer = m_buffer & sBuff

' update time for Asyn Event
m_currentTimeAsynEvent = GetTickCount()

if m_currentState = Waiting then
  m_currentState = Receiving
  InfinityLoop()
end if

InfinityLoop Method
verify that the expiration time has been reached

Content method

Dim current_time As Long        ' the time point o current time

 Do
     current_time = GetTickCount()
     ' timeout reach, exit of loop
     If current_time > m_currentTimeAsynEvent + m_timeOut Then
         Exit Do
     End If
     DoEvents
 Loop

 RaiseEvent StreamReceived(m_buffer)
 InitFlags 'Reset flags and variables

Примечание: , чтоожидаемый код с одним потоком, а не с несколькими ответами сокетов

...