簡體   English   中英

在 C# TCP IP 中發送和讀取多個 strcuts

[英]Sending And Read multiple strcuts in C# TCP IP

我想開發一種服務,該服務的服務器可以獲取多個連接並請求和讀取基於結構的數據。 現在的問題是如何從客戶端發送和接收多個結構並解密(或反序列化類似數據)。

如果您能在 C# 中閱讀如何執行此操作,那么獲得更多幫助真的很棒

客戶端代碼:

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;
    }
}

服務器代碼:

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;
    }
}

編寫 TCP/IP 應用程序非常困難。 如果有圖書館或 DLL 或已經為您處理協議的東西,請使用它。

如果您必須編寫自己的 TCP/IP 應用程序,那么我建議您觀看我關於異步 TCP/IP 的視頻系列以及閱讀我的TCP/IP .NET FAQ 然后閱讀您設備的協議文檔。 大概兩三次吧。

旁注:您可能不希望可空類型在您的 blittable 結構中。 就個人而言,這些天我避免使用 blittable 結構。 您可以改用BinaryPrimitives和朋友。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM