Search code examples
c#ctcpmemcpy

Sending C structs through TCP in C#


I am writing a program to interact with the management interface for a piece of equipment over TCP. The problem is, the documentation for the equipment is written in C, while the program I am writing is in C#. My problem is, the documentation specifies

The communication is based upon the C structure-based API buffer

No amount of Googling can seem to point me to this API or how I send a raw structure across TCP. The documentation seems to imply that I should use memcpy to copy the struct to the TCP buffer, but C# doesn't directly support memcpy. Is there an equivelant method in C# or a different way to accomplish this


Solution

  • You could build a .Net version of your C struct, then use marshalling to send a byte array through the network. Here's an example with the MLocation C struct.

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct MLocation
    {
        public int x;
        public int y;
    };
    
    public static void Main()
    {
        MLocation test = new MLocation();
    
        // Gets size of struct in bytes
        int structureSize = Marshal.SizeOf(test);
    
        // Builds byte array
        byte[] byteArray = new byte[structureSize];
    
        IntPtr memPtr = IntPtr.Zero;
    
        try
        {
            // Allocate some unmanaged memory
            memPtr = Marshal.AllocHGlobal(structureSize);
    
            // Copy struct to unmanaged memory
            Marshal.StructureToPtr(test, memPtr, true);
    
            // Copies to byte array
            Marshal.Copy(memPtr, byteArray, 0, structureSize);
        }
        finally
        {
            if (memPtr != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(memPtr);
            }
        }
    
        // Now you can send your byte array through TCP
        using (TcpClient client = new TcpClient("host", 8080))
        {
            using (NetworkStream stream = client.GetStream())
            {
                stream.Write(byteArray, 0, byteArray.Length);
            }
        }
    
        Console.ReadLine();
    }