Click to See Complete Forum and Search --> : [RESOLVED] Winsock DataArrival Event Problem
Napoleon
Apr 6th, 2006, 02:14 PM
Hi,
I'm writing a program that exchanges data between a host and a group of clients using TCP.
The problem I'm having is that when a client/host sends data to the host/client, if the size of the data stream exceeds the MTU, I am only getting the first MTU number of bytes.
So I am only able to receive the first DataArrival event, but not the subsequent ones (since they seem to never happen).
Outline of my code:
On the sending side, I break the data stream into chunks equal to the MTU or smaller, and send them in bursts (controlled by a timer set to 100mS intervals).
On the receiving side, I receive the data in the DataArrival Event handler into a TEXTBOX and then handover to another sub for processing (I am not using the CALL statement to execute the processor sub, just the name of the sub with the socket index parameter). The purpose of the textbox is to concatenate chuncks as they arrive.
The sub that does the processing initially copies the contents of the textbox into a string, and then uses the string thereafter. Since I'm only getting the first chunk, my stream is truncated and confuses the processing algorithm.
I suspect that it has something to do with being inside a procedure when the event takes place (I think it's since VB doesn't allow events while executing some procedures). I have put plenty of DOEVENTS statements into my code, but it still isn't working.
Does anyone have a detailed reference I can read that explains this aspect of EVENTS, and if possible, in relation to the Winsock control?
My code is about 800 lines or so long, so I didn't want to post it here. But if someone is interested enough, I can do so. (Or send via email attachment)
Cheers,
Nap.
ccoder
Apr 6th, 2006, 04:18 PM
I have an app that recieves records up to 27KB with no problem. Here is my DataArrival routine:
Private Sub tcpClient_DataArrival(ByVal bytesTotal As Long)
' determine the data type and process it
' get the buffer contents
ReDim gbIOBuff(bytesTotal)
tcpClient.GetData gbIOBuff, vbArray + vbByte, bytesTotal
If copyPtr = 0 Then ' we are at the beginning of a new reply
' save size & type of reply
CopyMemory recLen, gbIOBuff(0), 4 ' get the record length
recLen = ntohl(recLen) ' convert to little-endian
Debug.Print "Record size = " & recLen
CopyMemory codeCheck, gbIOBuff(52), 2 ' get the reply type
codeCheck = ntohs(codeCheck) ' convert to little-endian
ReDim gbReplyBuff(bytesTotal) ' clear old data record & start new one
Else
ReDim Preserve gbReplyBuff(copyPtr + bytesTotal) ' retain data & bump the size
End If
' copy the received data to the work buffer at location referenced by copyptr
CopyMemory gbReplyBuff(copyPtr), gbIOBuff(0), bytesTotal
If UBound(gbReplyBuff) = recLen Then
' we got the entire file
If codeCheck = glLocRequest Then
Process_Locations (recLen) ' called 1 time only at Form_Load
ElseIf codeCheck = glJobRequest Then
Process_JobStats (recLen) ' called for each chart request
Else
Beep
If codeCheck = glError Then
CopyMemory ErrIPC, gbIOBuff(0), bytesTotal
sbStatus.Panels(2).Text = "Error: " & codeCheck & ", " & _
Left$(ErrIPC.RepErrMsg, ErrIPC.RepMsgLen)
Else
sbStatus.Panels(2).Text = "Error: " & codeCheck & ", No data returned"
End If
intTics = 0 ' reset display timer
End If
copyPtr = 0 ' reset the flag\pointer
Else
' save the current record length\next copy location
copyPtr = UBound(gbReplyBuff)
End If
End Sub
The data is from a C application that sends the entire record in one send. TCP/IP, of course, breakes it into smaller packets. I know how large the record is from the first 4 bytes of the header and keep appending the incoming chunks until the record is complete. Once complete, I move the byte array buffer to the appropriate UDT for processing.
If you need more explanation of some of the code, let me know.
Napoleon
Apr 10th, 2006, 11:00 AM
CCoder,
I've fixed it now. Thanks for your ideas (testing number bytes received vs number sent).
I now have my Winsock_DataArrival event (inside a User Control) testing to see if it's received a complete message before it passes the data to the parent application.
I was previously passing each chunk (governed by the MTU) straight to the parent application without waiting. Thus, if the message was shorter than the MTU and didn't span 2 chunks, it was received ok, otherwise it was truncated.
Cheers,
Nap
milind_7001
May 17th, 2006, 12:34 AM
Hello ,
I m using VB Client connected to Java Server, Java Server sends me data in XML Format and TCP break and sends it in packets to my application. Now i want to identify starting and ending tags in XML.
If i found valid Starting and ending tags in XML, only then i send this data to processing and removes this valid XML data from original string and concatnate next coming data to the original string.
But i m not getting poper results. I think i m unable to buffer the data properly. Can u help to solve this problem ?
Napoleon
May 22nd, 2006, 01:30 PM
I have a User Control setup for all the winsock stuff.
In my application, when I send data, I preceed the data I'm sending with a number (X) (corresponding to the size of the total transmission).
In the client, I keep buffering the data until I have X bytes (plus the size of the data length number itself). Then I raise an event to the parent application that there is data.
I discovered the other day that if I send two small packets of data quickly, I only get one Data_Arrival event at the client end. So I've modified my receiving sub to scan through the whole buffer and pass all complete data streams.
The winsock control should have this 'chunk/data size' number somewhere within it, but I haven't been able to make it work for me. (Especially when the data length is larger than the MTU.)
In the mean time, I've evolved my code, and I suppose you could almost say reinvented TCP. I know this isn't the best way to do it, but it's working for me, and I will improve it over time.
Hope this helps a little,
Nap
kris.mogal
Apr 26th, 2008, 05:49 AM
Hi,
I am also facing the same problem, I am using a serial to ethernet converter to connect to one of my legacy hardware. I have a scenario like below.
1) Issue a command to my target hardware and it returns some 14 characters data.
2) In main application, I wait for '-', char in the received data at last position.
Ex:- sock.senddata "u0:2000"+ Chr(13)
do
str = str & recvdata
loop unitl right(str,1) = "-"
With this whenever there is data from my hardware dataarrival is not at all hitting. Then I have added almost 90000 Doevents in my app using a for loop counts 50 times and doevents statments in this loop approx 200. If I keep one DoEvent with a big loop again my DataArrival is not calling.
Ex:- sock.senddata "u0:2000"+ Chr(13)
for i = 1 to 50
DoEvents
.
.
next i
do
str = str & recvdata
loop unitl right(str,1) = "-"
Can you please let me know how can I achieve without using Doevents.
Rgds
Kris
vbforums.com
Copyright Internet.com Inc., All Rights Reserved.