2
votes

I have a C# Tcp server that sends messages to registered VB6 Tcp clients. The receiving of the message is done using WinSock in an asynchronous fashion. So the VB6 part where the "completed" message comes in looks like:

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

The problem that is that the C# Tcp server is sending a string of length 6874, but when we check the size of the message as received when the DataArrival event fires, it measure only 2920. So clearly this truncation of the incoming message is a severe problem.

Has anyone observed this before?

2

2 Answers

8
votes

As I said here VB6 WinSock TCP client and .NET TCP server:

That is a common misconception, that you are receiving messages. You are receiving a stream of bytes. sBuff may contain 1 byte, it may contain 50% of what makes up your message, often (if they are small enough) it can conatin 100% of your message, and sometimes it can contain more than 100% (meaning it has some part of the next message). Without seeing the code in ProcessMessage I cannot be sure you have a problem, but you should make sure that method can handle all of these scenarios

Just because you only see a data length of 2920 on DataArrival doesn't mean the data was truncated. It just means that that was all that was available at that moment. Read that data into a buffer, and then when the next part of the data you sent is available the event will fire again. Continue to read the available data and append to your buffer until you have the whole message.

1
votes

With mscomm control exists the same problem. Work with async events always its harded.

First that is my personal way of deal with it probably exist other way better. so it is one option more.

I've run into this problem more than one times and it often i forget how deal with that. so that also be my personal reference

First the idea

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

well we need understand how the events happen

Graphic view that be the dead time, the dead time just is a time period

Dead Time view

Now in vb6 when async events happen also need to happen two actions in different instant but are tested in the same moment

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

Also we will need some utility for keep track of time i used the win api GetTickCount

In mscomm also we will need add flag and string for know if some was received it for not wait so much in call to interface in the port

Also that code can throw event it for reuse and isolate

now see the skeleton of vb6 class

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

well now look at the 3 methods more closely

InitFlags Method

That clean variables and prepare the ambient, see the content

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

 

tcpControl_DataArrival Method

That method have the next responsibilities

   -update buffer 
   -initialize infinity loop 
   -update m_currentTimeAsynEvent

content of the method

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

Note: that code expected lead with a single stream not multiple socket responses