stucture data sending using udpmulticasting in C#

352 views Asked by At

I am trying to multicast struture data by converting it into byte array. Everything worked fine with below code except string variable's data of structure is not recieved at clients end as sent from server instead it is displaying empty string or other characters. Please suggest me to solve this problem.

Thanks inadvance.

Here is my code:

ServerCode

 struct CIFSPacket
        {
            public int quantity;
            public double price;
            public string Buffer;
        }
        static void Main(string[] args)
        {
            Socket server=null;
            try
            {
                server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                IPEndPoint iep = new IPEndPoint(IPAddress.Parse("224.100.0.1"), 9050);

                int i = 0;
                while (true)
                {
                    byte[] structData = new byte[4096];
                    //server.sendto
                    CIFSPacket pkt = new CIFSPacket();
                    pkt.quantity = i++;
                    pkt.price = i + 0.12;
                    pkt.Buffer = "RELIANCE";                    
                    structData = StructureToByteArray(pkt);
                    server.SendTo(structData, iep);                                        
                    Console.WriteLine(pkt.Buffer+" - "+pkt.quantity+" - "+pkt.price);                    
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                if (server != null)
                    server.Close();
            }
        }
private static byte[] StructureToByteArray(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;
        }

ClientCode

public struct CIFSPacket
        {
            public int quantity;
            public double price;
            public string Buffer;
        }

static void Main(string[] args)
        {
            Socket sock = null;
            CIFSPacket pkt;
            try
            {
                sock = new Socket(AddressFamily.InterNetwork,
                SocketType.Dgram, ProtocolType.Udp);
                Console.WriteLine("Ready to receive…");
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
                EndPoint ep = (EndPoint)iep;
                sock.Bind(iep);
                sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
                    new MulticastOption(IPAddress.Parse("224.100.0.1")));

                while (true)
                {
                    byte[] data = new byte[4096];                    
                    int recv = sock.ReceiveFrom(data, ref ep);                    
                    pkt = ByteArrayToStructure(data);
                    Console.WriteLine(pkt.Buffer + " -- " + pkt.quantity + " -- " + pkt.price);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                sock.Close();
                Console.ReadLine();
            }            
        }

private static CIFSPacket ByteArrayToStructure(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;
        }

Output

Server

Client

1

There are 1 answers

0
Denis  Yarkovoy On

The problem is that the string type in your structure is a managed pointer, not a value type.

Try replacing

 public string Buffer;

with

 [MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType=UnmanagedType.U2, SizeConst=Max_Size_Of_Your_String)]
 public char[] Buffer=new char[Max_Size_Of_Your_String];

Alternatively, you should be able to use

[MarshalAsAttribute(UnmanagedType.XXX)]

over your public string Buffer declaration, to tell the compiler how to convert your string to/from bytes. XXX is one of the supported string types, for example LPStr. But in this case you will need to specify maximum size of your string and/or structure in the corresponding attributes so that the compiler knows how much space to allocate for your string.

You may want to review the following articles for more information:

https://limbioliong.wordpress.com/2011/08/28/passing-managed-structures-with-strings-to-unmanaged-code-part-3/

convert struct handle from managed into unmanaged C++/CLI