简体   繁体   中英

Sending And Read multiple strcuts in C# TCP IP

I want to develop a service that have server which get multiple connection and requesting and read struct based data. Now problem is how to send and receive multiple structs from client and decrypt (or deserialize it for similar data).

It would be really cool to get more help where you can read how to do this in C#

Client code:

List<ResponseMessage> messages = new List<ResponseMessage>();

messages.Add
(
    new ResponseMessage()
    {
        cmd = 2,
        cmd_num = 4,
        client_id = 5,
        local_part_num = 1,
        end_buffer_address = 100500,
        group_id = 1
    }
);

messages.Add
(
    new ResponseMessage()
    {
        cmd = 2,
        cmd_num = 24,
        client_id = 11,
        local_part_num = 25,
        end_buffer_address = 300500,
        group_id = 33
    }
);



ResponseMessage message = new ResponseMessage();

using TcpClient tcpClient = new TcpClient();

Random rand = new Random();

try
{
    await tcpClient.ConnectAsync("127.0.0.1", 8888);

    var stream = tcpClient.GetStream();

    foreach(var msg in messages)
    {
        var byteArray = StructureToByteArray(msg);

        await stream.WriteAsync(byteArray, 0, byteArray.Length);
    }
}
catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}

/// <summary>
/// From structures to byte array
/// </summary>
byte[] StructureToByteArray(object obj)
{
    int size = Marshal.SizeOf(obj);

    byte[] arr = new byte[size];

    IntPtr ptr = Marshal.AllocHGlobal(size);

    Marshal.StructureToPtr(obj, ptr, true);

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

    Marshal.FreeHGlobal(ptr);

    return arr;
}


[StructLayout(LayoutKind.Sequential, Size = 12)]
struct RequestMessage
{
    public sbyte cmd;
    public byte cmd_num;
    public short rsvd;
    public int request_address;
    public int request_size;

    public RequestMessage()
    {
        cmd = 1;
        cmd_num = 200;
        rsvd = 0;
        request_address = 192133333;
        request_size = 350350333;
    }
}

[StructLayout(LayoutKind.Sequential, Size = 12)]
struct ResponseMessage
{
    public sbyte cmd;
    public byte? cmd_num;
    public short? local_part_num;
    public short? group_id;
    public short? client_id;
    public int? end_buffer_address;

    public ResponseMessage()
    {
        cmd = 2;
        cmd_num = 200;
        local_part_num = 1;
        group_id = 1;
        client_id = 4;
        end_buffer_address = 123213123;
    }
}

Server Code:

var tcpListener = new TcpListener(IPAddress.Any, 8888);

try
{

    tcpListener.Start();

    ResponseMessage responseMessage = new ResponseMessage();

    Program p = new Program();

    int ClientCounter = 0;

    while (true)
    {

        var tcpClient = await tcpListener.AcceptTcpClientAsync();


        NetworkStream stream = tcpClient.GetStream();

        ClientCounter++;

        try
        {
            byte[] responseData = new byte[1024];

            var response = new StringBuilder();

            int bytes = 0;

            StringBuilder responseBuilder = new StringBuilder();

            do
            {
                bytes = await stream.ReadAsync(responseData);

                responseMessage = FromBytes(responseData);
                 
                responseBuilder.Append($"{responseMessage.cmd} ");
                responseBuilder.Append($"{responseMessage.cmd_num} ");
                responseBuilder.Append($"{responseMessage.local_part_num} ");
                responseBuilder.Append($"{responseMessage.group_id} ");
                responseBuilder.Append($"{responseMessage.client_id} ");
                responseBuilder.Append($"{responseMessage.end_buffer_address}");

                Console.WriteLine(responseBuilder);

            }
            while (bytes > 0);

        }
        catch (Exception ex)
        {
            Console.WriteLine($"{ex.Message}");
            tcpClient.Close();
        }
    }
}
catch(Exception ex)
{
    Console.WriteLine($"{ex.Message}");
    tcpListener.Stop();
}


ResponseMessage FromBytes(byte[] arr)
{
    ResponseMessage responseMessage = new ResponseMessage();

    int size = Marshal.SizeOf(responseMessage);
    IntPtr ptr = IntPtr.Zero;

    try
    {
        ptr = Marshal.AllocHGlobal(size);

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

        var x = Marshal.ReadByte(ptr);

        responseMessage = (ResponseMessage)Marshal.PtrToStructure(ptr, responseMessage.GetType());
    }
    finally
    {
        Marshal.FreeHGlobal(ptr);
    }
    return responseMessage;
}


[StructLayout(LayoutKind.Sequential, Size = 12)]
struct RequestMessage
{
    public sbyte cmd;
    public byte cmd_num;
    public short rsvd;
    public int request_address;
    public int request_size;

    public RequestMessage()
    {
        cmd = 1;
        cmd_num = 200;
        rsvd = 0;
        request_address = 192133333;
        request_size = 350350333;
    }
}

Writing TCP/IP applications is extremely difficult. If there's a library or DLL or something that already does the protocol handling for you, then use that.

If you must write your own TCP/IP application, then I recommend watching my video series on asynchronous TCP/IP as well as reading my TCP/IP .NET FAQ . Then read your device's protocol document. Probably two or three times.

Side note: you probably don't want nullable types in your blittable structs. Personally, I avoid blittable structs these days; you can use BinaryPrimitives and friends instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM