tags:

views:

136

answers:

6

Hi,

How to Convert Structure to byte array in C# ?

I have defined a structure like this :

        public struct CIFSPacket
        {
            public uint protocolIdentifier;//the value must be "0xFF+'SMB'"
            public byte command;

            public byte errorClass;
            public byte reserved;
            public ushort error;

            public byte flags;


            //here there are 14 bytes of data which is used differently among different dialects.
            //I do want the flags2 however so I'll try parsing them
            public ushort flags2;

            public ushort treeId;
            public ushort processId;
            public ushort userId;
            public ushort multiplexId;
            //trans request
            public byte wordCount;//Count of parameter words defining the data portion of the packet.
            //from here it might be undefined...

            public int parametersStartIndex;

            public ushort byteCount;//buffer length
            public int bufferStartIndex;

            public string Buffer;


        }

In my main method i create a instance of it and assign values to it

            CIFSPacket packet = new CIFSPacket();
            packet.protocolIdentifier = 0xff;
            packet.command = (byte)CommandTypes.SMB_COM_NEGOTIATE; 
            packet.errorClass = 0xff;
            packet.error = 0;
            packet.flags = 0x00;
            packet.flags2 = 0x0001;
            packet.multiplexId = 22; 
            packet.wordCount = 0; 
            packet.byteCount = 119;    

            packet.Buffer = "NT LM 0.12";

Now i want send this Packet by socket for that i need to convert Structute to byte array ..How i can do it ??

My full code is as follows :

        static void Main(string[] args)
        {

          Socket MyPing = new Socket(AddressFamily.InterNetwork,
          SocketType.Stream , ProtocolType.Unspecified ) ;


          MyPing.Connect("172.24.18.240", 139);  

            //Fake an IP Address so I can send with SendTo
            IPAddress IP = new IPAddress(new byte[] { 172,24,18,240 });
            IPEndPoint IPEP = new IPEndPoint(IP, 139);

            //Local IP for Receiving
            IPEndPoint Local = new IPEndPoint(IPAddress.Any, 0);
            EndPoint EP = (EndPoint)Local;

            CIFSPacket packet = new CIFSPacket();
            packet.protocolIdentifier = 0xff;
            packet.command = (byte)CommandTypes.SMB_COM_NEGOTIATE; 
            packet.errorClass = 0xff;
            packet.error = 0;
            packet.flags = 0x00;
            packet.flags2 = 0x0001;
            packet.multiplexId = 22; 
            packet.wordCount = 0; 
            packet.byteCount = 119;    

            packet.Buffer = "NT LM 0.12";






            MyPing.SendTo(It takes byte array as parameter);



        }

Any code snippet pls

A: 

I would take a look at the BinaryReader and BinaryWriter classes. I recently had to serialize data to a byte array (and back) and only found these classes after I'd basically rewritten them myself.

http://msdn.microsoft.com/en-us/library/system.io.binarywriter.aspx

There is a good example on that page too.

AndrewS
A: 

Quote from Wikipedia - In computer science, in the context of data storage and transmission, serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be "resurrected" later in the same or another computer environment.

For introduction in serialization in C# look here. You should use a BinaryFormatter with a MemoryStream like here to get the byte array.

Petar Minchev
One more thing...After converting to byte array and send through socket ...How i can check response is coming or not ?
Swapnil Gupta
@Swapnil that's a completely separate problem, best handled as another question rather than just a comment.
Nathan Tomkins
A: 

Looks like a predefined (C level) structure for some external library. Marshal is your friend. Check:

http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx

for a starter how to deal with this. Note that you can - with attributes - define things like byte layout and string handling. VERY nice approach, actually.

Neither BinaryFormatter Nor MemoryStream are done for that.

TomTom
+1  A: 

Have a look at these methods:

byte [] StructureToByteArray(object obj)
{
int len = Marshal.SizeOf(obj);

byte [] arr = new byte[len];

IntPtr ptr = Marshal.AllocHGlobal(len);

Marshal.StructureToPtr(obj, ptr, true);

Marshal.Copy(ptr, arr, 0, len);

Marshal.FreeHGlobal(ptr);

return arr;
}
void ByteArrayToStructure(byte [] bytearray, ref object obj)
{

int len = Marshal.SizeOf(obj);

IntPtr i = Marshal.AllocHGlobal(len);

Marshal.Copy(bytearray,0, i,len);

obj = Marshal.PtrToStructure(i, obj.GetType());

Marshal.FreeHGlobal(i);

}

This is a shameless copy of another thread which I found upon Googling!

Update : For more details, check the source

Abdel Olakara
@Abdel : Why Shamless Copy ?
Swapnil Gupta
-1, you should provide a link to the original thread.
Alastair Pitts
I have converterd Structure to byte array using Marshalling now how i can check whether I am getting the response from socket ? How to check that ?
Swapnil Gupta
@Alastair, I missed that out!! Thanks for pointing it.. I have updated my answer.
Abdel Olakara
This option is platform dependent - Take care about Grand Endian and Little endian and about 32 Bits / 64 bits.
x77
@Abdel, and the -1 is gone :)
Alastair Pitts
+1  A: 

This is fairly easy, using marshalling.

Top of file

using System.Runtime.InteropServices

Function

byte[] getBytes(CIFSPacket str) {
    int size = Marshal.SizeOf(str);
    byte[] arr = new byte[size];
    IntPtr ptr = Marshal.AllocHGlobal(size);

    Marshal.StructureToPtr(str, ptr, true);
    Marshal.Copy(ptr, arr, 0, size);
    Marshal.FreeHGlobal(ptr);

    return arr;
}

And to convert it back:

CIFSPacket fromBytes(byte[] arr) {
    CIFSPacket str = new CIFSPacket();

    int size = Marshal.SizeOf(str);
    IntPtr ptr = Marshal.AllocHGlobal(size);

    Marshal.Copy(arr, 0, ptr, size);

    str = (CIFSPacket)Marshal.PtrToStructure(ptr, str.GetType());
    Marshal.FreeHGlobal(ptr);

    return str;
}

In your structure, you will need to put this before a string

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string Buffer;

And make sure SizeConst is as big as your biggest possible string.

And you should probably read this: http://msdn.microsoft.com/en-us/library/4ca6d5z7.aspx

Vincent McNabb
Thanks Vincet. GetBytes() should be called after sending the byte[]?? and frombytes() method is sending the bytes ?I am little confused buddy ?
Swapnil Gupta
GetBytes converts from your structure to an array. FromBytes converts from the Bytes back to your structure. This is evident from the function signatures.
Vincent McNabb
Also, if you find that an answer works for you, you should accept it. Your 0% accept rate is going to make people less likely to answer your questions.
Vincent McNabb
@Vincet : That's fine Vincet.Now i want to get the response back .How i can do that ? How can check my response ?
Swapnil Gupta
Thanks Vincet. I have marked your answer. Pls how to get response back can u pls tell me ? Thanks in Advance.
Swapnil Gupta
Response back for what?
Vincent McNabb
@Vincet : Now i have to get response from Socket that what ever CIFS packet i have send it has got it ? How to check that ?
Swapnil Gupta
@Swapnil That is another question, which you should ask separately. You should consider completing a couple of CE tutorials on sockets. Just search Google.
Vincent McNabb
A: 

You can use Marshal (StructureToPtr, ptrToStructure), and Marshal.copy but this is plataform dependent.


Serialization includes Functions to Custom Serialization.

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext) 

SerializationInfo include functions to serialize each member.


BinaryWriter and BinaryReader also contains methods to Save / Load to Byte Array (Stream).

Note that you can create a MemoryStream from a Byte Array or a Byte Array from a MemoryStream.

You can create a method Save and a method New on your structure:

   Save(Bw as BinaryWriter)
   New (Br as BinaryReader)

Then you select members to Save / Load to Stream -> Byte Array.

x77