none
Serialization exception with custom data format RRS feed

  • Question

  • Hello everyone!

    I am working on a server-client application and I'm using my own version of byte formatting to get the server to recieve multiple messages and not crash(it should know where one object ends and another begins in the stream). So I wrote two functions that Format bytes and Deformat them from a stream:

    Public Function DeformatBytes(ByVal s As NetworkStream) As Byte()
            Dim firstByte As Integer = s.ReadByte()
            If firstByte > 0 Then
                Dim lnBytes(firstByte - 1) As Byte
                s.Read(lnBytes, 0, firstByte)
                Dim realLength As UInteger = 0
                For i As Integer = 0 To firstByte - 1
                    Dim bytToChange As UInteger = lnBytes(i)
                    realLength += (bytToChange << (8 * (firstByte - 1 - i)))
                Next
                Dim retBytes(realLength - 1) As Byte
                s.Read(retBytes, 0, realLength)
                Return retBytes
            Else
                Return {}
            End If
        End Function
    
        Public Function FormatBytes(ByVal b() As Byte) As Byte()
            Dim byteLen As UInteger = b.Length
            If byteLen = 0 Then Return {}
    
            Dim len2 As UInteger = byteLen
            Dim n As Integer=0
            While len2 > 0
                len2 >>= 8
                n += 1
            End While
            len2 = byteLen
    
            Dim lenBytes(n - 1) As Byte
            For i As Integer = 0 To n - 1
                Dim shifter As Integer = 8 * (n - 1 - i)
                If shifter = 0 Then
                    lenBytes(i) = len2
                Else
                    lenBytes(i) = len2 >> shifter
                    len2 -= (CUInt(lenBytes(i)) << shifter)
                End If
            Next
            
            Dim fullB(n + b.Length) As Byte
            fullB(0) = n
            lenBytes.CopyTo(fullB, 1)
            b.CopyTo(fullB, n + 1)
            Return fullB
        End Function

    It basically works like this: before writing an object that's been deserialized to a stream, I format the resulting bytes.

    1. Calculate how many bytes it takesn) to write down the length of the object byte array
    2. Compose a new byte array representing 'n' in binary order(first byte in array is MSB and last is LSB)
    3. Make a new byte array, in which the first byte is how many bytes does the array in step 2 take up, the following bytes are the array in step 2, ending with all the bytes we inputed for formatting

    After data is available on the stream(Stream.DataAvailable in a seperate thread looping until it's true), I use the DeformatBytes function which does the opposite of FormatBytes:

    1. Get the first byte
    2. Make a byte buffer to hold the bytes that make up the length of the data array and read bytes from the stream into this new buffer
    3. Calculate the length of the data array (realLength)
    4. Make a new buffer to hold the data
    5. Read n bytes from the stream into buffer from step 4 and return the buffer

    The problem is, that sometimes I get a SerializationException saying there's something wrong with the bytes I'm trying to deserialize(usually invalid binary header). I'm suspecting that might be because the functions I wrote cut off the array too short of it's length or something like that. Data loss is probably not the explanation since I'm using a TCP client. What am I doing wrong?


    • Edited by suzi9spal Monday, May 11, 2015 9:41 AM Variable misstype
    Monday, May 11, 2015 9:35 AM

Answers

  • Hi suzi9spal,
      As per my understanding of your code snippet , I found the mistakes in FormatBytes() function.
    If byteLen is equal to 0 then returns empty {} . after that there is no else part of this current if condition.so it also execute the next line.so it create & try to return the value of new byte (fullB) again. I suspect that this might be the root cause.

    for your reference, you can modify the FormatBytes() function like below :

    Public Function FormatBytes(ByVal b() As Byte) As Byte()

        Dim byteLen As UInteger = b.Length

        If byteLen = 0 Then

              Return {}

        Else

                                    Dim len2 As UInteger = byteLen

                                    Dim n As Integer=0

                                    While len2 > 0

                                    len2 >>= 8

                                    n += 1

                                    End While

                                    Dim lenBytes(n - 1) As Byte

                                    For i As Integer = 0 To n - 1

                                    Dim shifter As Integer = 8 * (n - 1 - i)

                                    If shifter = 0 Then

                                                    lenBytes(i) = len2

                                    Else

                                                    lenBytes(i) = len2 >> shifter

                                                    len2 -= (CUInt(lenBytes(i)) << shifter)

                                    End If

                                    Next

           

                                    Dim fullB(n + byteLen ) As Byte

                                    fullB(0) = n

                                    lenBytes.CopyTo(fullB, 1)

                                    b.CopyTo(fullB, n + 1)

                                    Return fullB

      End If  

    End Function

    Wednesday, May 13, 2015 1:03 AM
  • hi Suzi9spal,
       As per this case, If the array length is not sufficient, then increase its length . you can check
    If byteLen <> 0

    put your rest of the code here instead of Return {}

    Moreover I suggest you to use try-catch block to find out the exact exception which may guide you to fix the issue.

    Friday, May 22, 2015 8:01 AM

All replies

  • Hi suzi9spal,
      As per my understanding of your code snippet , I found the mistakes in FormatBytes() function.
    If byteLen is equal to 0 then returns empty {} . after that there is no else part of this current if condition.so it also execute the next line.so it create & try to return the value of new byte (fullB) again. I suspect that this might be the root cause.

    for your reference, you can modify the FormatBytes() function like below :

    Public Function FormatBytes(ByVal b() As Byte) As Byte()

        Dim byteLen As UInteger = b.Length

        If byteLen = 0 Then

              Return {}

        Else

                                    Dim len2 As UInteger = byteLen

                                    Dim n As Integer=0

                                    While len2 > 0

                                    len2 >>= 8

                                    n += 1

                                    End While

                                    Dim lenBytes(n - 1) As Byte

                                    For i As Integer = 0 To n - 1

                                    Dim shifter As Integer = 8 * (n - 1 - i)

                                    If shifter = 0 Then

                                                    lenBytes(i) = len2

                                    Else

                                                    lenBytes(i) = len2 >> shifter

                                                    len2 -= (CUInt(lenBytes(i)) << shifter)

                                    End If

                                    Next

           

                                    Dim fullB(n + byteLen ) As Byte

                                    fullB(0) = n

                                    lenBytes.CopyTo(fullB, 1)

                                    b.CopyTo(fullB, n + 1)

                                    Return fullB

      End If  

    End Function

    Wednesday, May 13, 2015 1:03 AM
  • Hello Edwin,

    I am thankfull for your help and I will test the fix as soon as I cam, but as far as I know once you return a value the function no longer executes the remaining lines. Furthermore, the formatbytes function is never called with an ampty array, since the object I'm serializing is never null.

    Thank you for your help,

    Suzi9spal


    • Edited by suzi9spal Wednesday, May 13, 2015 6:38 PM
    Wednesday, May 13, 2015 9:40 AM
  • hi Suzi9spal,
       As per this case, If the array length is not sufficient, then increase its length . you can check
    If byteLen <> 0

    put your rest of the code here instead of Return {}

    Moreover I suggest you to use try-catch block to find out the exact exception which may guide you to fix the issue.

    Friday, May 22, 2015 8:01 AM