Results 1 to 13 of 13

Thread: buffering an incoming data

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    buffering an incoming data

    hie all,
    suppose i receive a tcp packet with the begining with "02 00 0C..........................."
    all the incoming tcp packet start with "02" so, how do i buffer a tcp packet till i receive the complete packet??
    Last edited by pannam; Jun 19th, 2008 at 01:36 PM.

  2. #2
    Fanatic Member
    Join Date
    Jan 2007
    Location
    Middletown, CT
    Posts
    948

    Re: buffering an incoming packet!

    I'd say to create a byte array and put the data into element 0 of the byte array, then redim the array with each byte until you reach another 02, at which point you'd start filling the next array while processing that one.

    Alternatively, if your packets are of a standard size (which they should be) create a byte array of that size and simply fill it with the incoming data until it's full.

    However, there are plenty of TCP/IP controls out there, I'd look into those instead of trying to make your own. Maybe even a few API calls?

  3. #3
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: buffering an incoming packet!

    Very few protocols frame messages (not packets) by signaling the start of a new message. If you try to do this the receiver will always have to wait for the start of a new message before knowing the previous one is finished.

    It is much more likely that there is either some length field within the header (first few bytes) or else some delimiting character or character sequence at the end of each message.

  4. #4
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: buffering an incoming packet!

    The length of the data should be in the header like dilettante said. If you are coding a mig33 client. I remember glancing at the protocol documentation that you posted and the header should contain the length.

    These kind of protocols are a little harder to work with than ones that just delimit packets with a special sequence like vbCrLf or something.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    Re: buffering an incoming packet!

    thank you for your suggestion guyz ...i better code with the header instead of buffering all the packet and waiting for the other packet to arrive..

  6. #6
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: buffering an incoming packet!

    Declare a form-scope variable for the buffer, like:

    vb Code:
    1. Option Explicit
    2.  
    3. Private strBuffer As String

    On DataArrival, get the data into a string, and append it into the buffer, like:

    vb Code:
    1. strBuffer = strBuffer & ReceivedData

    Then process the buffer one packet at a time. Once a packet from the buffer has been processed, remove it from the buffer, doing something like:

    vb Code:
    1. 'Packet processed.
    2. strBuffer = Mid$(strBuffer, LengthOfPacket + 1)

    If you need help with this, then post a URL to the protocol documentation and your current code.

  7. #7
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,334

    Re: buffering an incoming packet!

    The mig33 protocol (http://www.devinsmith.net/articles/m...#Communication) is a bit tricky, but I'd start off by defining a UDT to represent the fixed length portion of the Header. Once you've received that, the Command1 and Command2 codes will determine the format of the rest of the data.
    Code:
    Private Type migHeader
        Magic As Byte
        Command1(1) As Byte
        Command2(1) As Byte
        Pack_Len(3) As Byte
    End Type
    
    Private bytBuffer() As Byte
    
    Private Sub Form_Load()
    '
    ' Allocate some initial space for the Buffer
    ' (100 bytes)
    '
    ReDim bytBuffer(99)
    End Sub
    
    Private Sub ws_DataArrival(ByVal bytesTotal As Long)
    Dim udtHead As migHeader
    Dim bytRx() As Byte
    Static lngLast As Long          ' This points to the next free element in the buffer
    Dim lngBufLen As Long
    Dim intI As Integer
    '
    ' Read the data
    ' Calculate whether it will fit into the buffer
    ' and extend the buffer if required
    '
    ws.GetData bytRx
    lngBufLen = lngLast + UBound(bytRx)
    If lngBufLen > UBound(bytBuffer) Then ReDim Preserve bytBuffer(UBound(bytBuffer) + 100)
    '
    ' Add the data received into the buffer
    '
    For intI = lngLast To lngLast + UBound(bytRx)
        bytBuffer(intI) = bytRx(intI - lngLast)
    Next intI
    lngLast = intI
    '
    ' If we have received enough data then populate
    ' the header
    '
    If UBound(bytBuffer) >= Len(udtHead) Then
        Copymemory udtHead, bytBuffer(0), Len(udtHead)
    You now have a design decision to make in order to interpret the Command1 and Command2 values, (actually you should have made that decision before writing any code ) within the UDT they are stored as two byte arrays. You could inspect each one in turn to determine the Command or you could cast them to two Integer values and use those or you could cast all 4 bytes to a Long variable and use that. If you cast to Integer or Long you'll have to remember that the bytes will be stored as Little Endian (ie reversed) and you may end up with some 'funny' values.

    For example, the Protocol defines Command1 = 00 CB and Commad2 = 00 02 for the LOGIN_OK / MOTD message.

    Casting those two values from the byte arrays to integers would result in intCommand1 = CB 00 (-13568) and intCommand2 = 02 00 (512) which is not necessarily intuitive when compared to the original Protocol values.

    Casting the 4 bytes to a Long would result in 02 00 CB 00 (33606400).

    Bearing in ,mind that you will have to fiddle around with the length values in order to cast them properly, I'd be tempted to store them in reverse order when 'casting' to Integer or Long types in which case they would retain their values as defined in the protocol. (Using the ByteToInteger and ByteToLong functions I mentioned in your other thread: http://www.vbforums.com/showthread.php?t=524353)
    Code:
    Option Explicit
    
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
                (Destination As Any, _
                 Source As Any, _
                 ByVal Length As Long)
    
    Private Const LOGIN_OK1 As Integer = 203
    Private Const LOGIN_OK2 As Integer = 2
    '
    ' Insert other Protocol Constants here
    '
    Private Type migHeader
        Magic As Byte
        Command1(1) As Byte
        Command2(1) As Byte
        Pack_Len(3) As Byte
    End Type
    
    Private bytBuffer() As Byte
    
    Private Sub Form_Load()
    '
    ' Allocate some initial space for the Buffer
    ' (100 bytes)
    '
    ReDim bytBuffer(99)
    End Sub
    
    Private Sub ws_DataArrival(ByVal bytesTotal As Long)
    Dim udtHead As migHeader
    Dim bytRx() As Byte
    Static lngLast As Long          ' This points to the next free element in the buffer
    Dim lngBufLen As Long
    Dim boComplete As Boolean
    Dim intI As Integer
    Dim intCommand1 As Integer
    Dim intCommand2 As Integer
    Dim lngPackLen As Long
    '
    ' Read the data
    ' Calculate whether it will fit into the buffer
    ' and extend the buffer if required
    '
    ws.GetData bytRx
    lngBufLen = lngLast + UBound(bytRx)
    If lngBufLen > UBound(bytBuffer) Then ReDim Preserve bytBuffer(UBound(bytBuffer) + 100)
    '
    ' Add the data received into the buffer
    '
    For intI = lngLast To lngLast + UBound(bytRx)
        bytBuffer(intI) = bytRx(intI - lngLast)
    Next intI
    lngLast = intI
    Do
        '
        ' If we have received enough data then populate
        ' the header
        '
        If UBound(bytBuffer) >= Len(udtHead) Then
            CopyMemory udtHead, bytBuffer(0), Len(udtHead)
            intCommand1 = ByteToInteger(udtHead.Command1, 0)
            intCommand2 = ByteToInteger(udtHead.Command2, 0)
            lngPackLen = ByteToLong(udtHead.Pack_Len, 0)
            '
            ' lngPackLen is the total length of the Pay Load
            ' less 9. This can be used to determine if the
            ' complete message has been received
            '
            If lngPackLen + 9 <= lngLast - 1 Then
                '
                ' We have at least one complete message
                ' Now we can determine what sort of message it is and unblock it
                '
                Select Case intCommand1
                    Case LOGIN_OK1
                        Select Case intCommand2
                            Case LOGIN_OK2
                                '
                                ' Code to process the LOGIN_OK message
                                '
                            '
                            ' Extra Command2 selections go here
                            '
                        End Select
                        '
                        ' Extra Command1 and their Command2 selections go here
                        '
                End Select
                '
                ' Having processed the complete message
                ' we have to inspect the buffer to see the there's
                ' another message or part of a message left in it
                ' if there is, then we have to jiggle around with it and
                ' process it.
                ' Otherwise flush the buffer and exit
                '
                If lngLast > lngPackLen + 9 Then
                    '
                    ' There's more data
                    ' shuffle it to the front of the buffer
                    '
                    For intI = lngPackLen + 9 To lngLast - 1
                        bytBuffer(intI - lngPackLen) = bytBuffer(intI)
                    Next intI
                    lngLast = intI
                Else
                    ReDim bytBuffer(99)
                    lngLast = 0
                End If
            Else
                boComplete = True
            End If
        Else
            boComplete = True
        End If
    Loop Until boComplete = True
    End Sub
    
    Private Function ByteToLong(byt() As Byte, lng As Long) As Long
    Dim intI As Integer
    Dim lngVal As Long
    For intI = 0 To 3
        CopyMemory ByVal VarPtr(lngVal) + 3 - intI, byt(intI + lng), 1
    Next intI
    ByteToLong = lngVal
    End Function
    
    Private Function ByteToInteger(byt() As Byte, lng As Long) As Integer
    Dim intI As Integer
    Dim intVal As Integer
    For intI = 0 To 1
        CopyMemory ByVal VarPtr(intVal) + 1 - intI, byt(intI + lng), 1
    Next intI
    ByteToInteger = intVal
    End Function
    Note that none of the code above is tested in any way shape or form (except the ByteTo.. functions) and is probably littered with errors. However the Logic is sound (and is only one of many possible ways you can approach it). Others with more experience and knowledge will have other ideas and most probably better implementations. eg Using a string buffer as opposed to a byte buffer will simplify buffer management, but I think that's actually the least of the problems. This could be a 'starter-for-10'.
    Last edited by Doogle; May 31st, 2008 at 02:07 AM. Reason: Corrected Calls to ByteTo.... Functions

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    Re: buffering an incoming packet!

    oh Doogle you have put in such an effort ..i honestly thought this thread would be left as it is...thank you very much ..although i have reached quite far with my project i will still practice what you have taught and let you know..thank you very much once again..

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    Re: buffering an incoming packet!

    hey guyz ..thanx for replying ..@Doogle i had taken your #6 post into consideration and wrote my code...i don't know wether this way works or not ..if not i will move on to your latter posts..this is the way i am trying to buffer ..my module
    Code:
    Public Function cSizeHex(buff As String) As String
    Dim pcklen As Integer
    pcklen = Len(buff)
    Dim FstNum As String
    FstNum = 0
    Do While pcklen > 255
    FstNum = FstNum + 1
    pcklen = pcklen - 256
    Loop
    cSizeHex = " " & Hex(FstNum) & " " & Hex(pcklen) & " "
    End Function
    lets say a packet arrives in my winsock_data arrival event
    Code:
     02 01 F4 00 00 00 00 00 5B 00 02 00 00 00 0A 
    62 65 72 6C 69 6E 77 61 6C 6C 00 04 00 00 00 0A 62 
    65 72 6C 69 6E 77 61 6C 6C 00 08 00 00 00 1F 43 75 
    72 72 65 6E 74 6C 79 20 69 6E 20 74 68 65 20 72 6F 
    6F 6D 3A 20 77 69 72 65 77 6F 72 6D 00 06 00 00 00 
    02 00 01 00 01 00 00 00 01 01 00 03 00 00 00 01 03
    5B is the length of the packet from there till the end i.e. 03 = 91

    and in my winsockdata arrival i have this code
    Code:
     Private Sub sock1_DataArrival(ByVal bytesTotal As Long)
    
    Dim strHeader As String
    sock1.GetData dat, vbString
    strHeader = Left(dat, 3)
    Select Case strHeader
    case is = HextoAscii("02 01 F4")
    '''''''''here i want to write a code that can buffer the whole packet'''
    '''code to be processed''
    end select
    end sub

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    Re: buffering an incoming packet!

    as each of the tcp data ends with 03 i added this buffer and it works
    Code:
     If Right$(strBuffer, 1) <> HextoAscii("03") Then
          bolTrunc = True
            lonTruncStart = InStrRev(strBuffer, HextoAscii("03"))
            If lonTruncStart > 0 Then
              ' MsgBox "true"
                strTrunc = Mid$(strBuffer, lonTruncStart + 1)
            End If
        End If
        
        If InStr(1, strBuffer, HextoAscii("03")) > 0 Then
            strPackets() = Split(strBuffer, HextoAscii("03"))
            lonUB = UBound(strPackets)
            
            If bolTrunc Then lonUB = lonUB - 1
            
            For lonLoop = 0 To lonUB
                If Len(strPackets(lonLoop)) > 3 Then
    Select Case Left$(strPackets(lonLoop), 3)
    'code to process
    end select
    End If
            Next lonLoop
        
        End If
        
        Erase strPackets
        
        strBuffer = vbNullString
        
        If bolTrunc Then
            strBuffer = strTrunc
        End If
        
        strTrunc = vbNullString
    althought the above code works ,i don't think its complete ..as sometimes a msg that has only 3 letters in it too has 03 infront of it which marks the length of the message ..the first byte is always 02 ,the length of the tcp data is in the 9th byte if i were to buffer it from there what else do i have to add in my code ?? i am bringing this up as you guyz have mentioned about getting the length of the data from the header..
    Last edited by pannam; Jun 19th, 2008 at 01:37 PM.

  11. #11

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    Re: buffering an incoming data

    hey Doogle i get compile error as expected array in this part
    Code:
     ws.GetData bytRx
    lngBufLen = lngLast + UBound(bytRx)
    If lngBufLen > UBound(bytBuffer) Then ReDim Preserve bytBuffer(UBound(bytBuffer) + 100)

  12. #12
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,334

    Re: buffering an incoming data

    Hi, If you look atPost #7 you'll see that bytBuffer is defined thus:
    Code:
    Private bytBuffer() As Byte
    in the Declarations Section of the Form as a Dynamic Byte Array. I suspect you have missed of the '()' or defined bytBuffer in the wrong place.

  13. #13

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2008
    Posts
    327

    Re: buffering an incoming data

    hey, doogle i got the code working i re-wrote all my code according to what you provided me.. but as i need to use ascii string as out put in my text box i used this code
    Code:
    dat = StrConv(bytRx, vbUnicode)
    initially i ran into some trouble because i couldn't get the required header to process the data and it didn show up in select case ..so, i changed your code
    Code:
    If lngPackLen + 9 <= lngLast - 1 Then
    to
    Code:
    If lngPackLen + 8 <= lngLast - 1 Then
    doing this i am able to process the data ,i get the hash string from the server (38 byte) ..and i send the login response , but i am getting errors when i receive the login ok packet.. subscription out of range in
    Code:
      bytBuffer(intI) = bytRx(intI - lngLast)
    i didn make any other changes and i am waiting for your reply.
    Last edited by pannam; Jun 22nd, 2008 at 10:08 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width