[英]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.