locked
Converting structure within structure to byte array for socket RRS feed

  • Question

  • Hi,

    I am trying to communicate with an external device and i am trying to send a byte array to the external device via sockets but i am always getting a response the message size is too small so i am not sure what i have done wrong. Between the data type there should be no alignment present and all numbers are represented in little endian format. The char array is not null terminated as mentioned in the protocol specifications.

    I have to send data based on a struct that embeds 2 other struct. So here's my vb.net code for the struct used to convert to byte array and the sending part. Thanks in advance.

    Public Structure MESSAGETYPE_OIP_Login
            Dim Header() As COMMANDHEADER
            Dim UserName() As PSTRING
            Dim Password() As PSTRING
        End Structure
       
        Public Structure COMMANDHEADER
            Dim MessageType As UInt32
            Dim Length As UInt32
            Dim Reserved1 As UInt32
            Dim Reserved2 As UInt32
        End Structure
    
        Public Structure PSTRING
            Dim Length As UInt32
            Dim CharArray() As Char
        End Structure
    
    
    Dim client as System.Net.Sockets.TcpClient = New  System.Net.Sockets.TcpClient("192.168.20.93", 9401)
    
    Dim networkStream As Net.Sockets.NetworkStream = client.GetStream()
    
            Dim Login As MESSAGETYPE_OIP_Login
    
            Login.Header.MessageType = 4485122
            Login.Header.Reserved1 = 0
            Login.Header.Reserved2 = 0
            Login.Header.Length = Marshal.SizeOf(Login.Header)
    
            Login.UserName.CharArray = "admin".ToCharArray
            Login.UserName.Length = Login.UserName.CharArray.Length
    
            Login.Password.CharArray = "admin".ToCharArray
            Login.Password.Length = Login.Password.CharArray.Length
    
            Dim StrtoBy() As Byte
    
    
            Dim ptr As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(Login))
            
            ReDim StrtoBy(Marshal.SizeOf(Login) - 1)
            Marshal.Copy(ptr, StrtoBy, 0, Marshal.SizeOf(Login))
            Marshal.FreeCoTaskMem(ptr)
    
            networkStream.Write(StrtoBy, 0, StrtoBy.Length)
    Saturday, August 29, 2009 6:17 AM

All replies

  • Is that really your code? It shouldn't even compile You're declaring for example Header as an array

    Dim Header() As COMMANDHEADER

    but accessing it like a single field

    Login.Header.MessageType = 4485122

    Marshal.SizeOf will not return the length you expect when used on structs with variable length arrays like PSTRING.CharArray. Therefore I don't think the Marshal class is the best solution here.

    Have you considered writing member by member to the stream by wrapping a BinaryWriter around it instead?

    Mattias, C# MVP
    Monday, August 31, 2009 1:10 PM
  • hi,

    Sorry about that array i forgot to take it off after changing it to normal.

    Yes, the thing worked when i write member by member to the stream.

    When i use marshal.copy i realised that all the bytes are not in the order even after i specified structlayout = explicit and <fieldoffset> and marshal.structureToPtr works only when the structure members is only the basic .net datatype (not sure about this as i am pretty new to this) or i will get unable to access protected memory area.

    I have 30 over different structures so writing stream by stream is very tedious that's why i am trying to look for ways where i can simplified this.

    Monday, August 31, 2009 1:26 PM