gpt4 book ai didi

c# - 如何以二进制帧格式发送数据(TCP)

转载 作者:可可西里 更新时间:2023-11-01 02:33:25 25 4
gpt4 key购买 nike

我需要将数据流式传输到 TCP 服务器并且之前没有做过。数据应为二进制帧格式。我用谷歌搜索并找到了这个教程,我认为它描述了我需要做的事情:

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient(v=vs.71).aspx

但我不知道如何以所需的格式创建数据,以便以正确的方式发送它。它应该是这种格式:

Field|Offset|    Type  | size(octets)
id | 0 |unsign int| 1
name | 1 |Byte Array| 40
grade| 41 |sign float| 8

例子:

Field| Data | InBytes  |
id | 133 | 133 |
name | 247 | 247 0 |
grade| 0 | 0 |

我应该将 int、字节数组、 float 存储在什么数据类型中,我应该在哪里指定偏移量和大小,最后应该如何将它发送到服务器(在示例中,它们只发送一个字节数组)。

一个 C# 示例如何使用上面提供的链接中的代码发送这样的数据将不胜感激。

最佳答案

要表示要序列化(和反序列化)的数据,您可以使用结构并设置适当的元数据,让 CLR 为您完成剩下的工作。就像其他人在这里所说的那样,您需要处理端点上的数据包接收。此外,您还必须考虑接收方期望的字符集,因为您的数据中有一个字符串字段。以下代码是一个示例,说明如何实现该结构以将托管数据转换为二进制格式,并带有注释。

// setting the layout to sequential will prevent the compiler/JIT
// to reorder the struct fields
// NOTE: Observe here that the Charset used is Ansi. You may need to
// change this depending on the format expected by the receiver.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct DataPacket
{

[MarshalAs(UnmanagedType.U4)]
public uint Id;

// As I understood from your question, the Name field
// has a prefixed size of 40 bytes. Attention here:
// the SizeConst actually means '40 characters', not bytes
// If you choose to use the Unicode charset, set SizeConst = 20
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public String Name;

// This will be serialized in little endian format
// in your question this field is 8 bytes long, which
// in c# corresponds to the double type. If you really mean
// the float type (4 bytes), change here.
public double Grade;

// Calling this method will return a byte array with the contents
// of the struct ready to be sent via the tcp socket.
public byte[] Serialize()
{
// allocate a byte array for the struct data
var buffer = new byte[Marshal.SizeOf(typeof(DataPacket))];

// Allocate a GCHandle and get the array pointer
var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
var pBuffer = gch.AddrOfPinnedObject();

// copy data from struct to array and unpin the gc pointer
Marshal.StructureToPtr(this, pBuffer, false);
gch.Free();

return buffer;
}

// this method will deserialize a byte array into the struct.
public void Deserialize(ref byte[] data)
{
var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
this = (DataPacket)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(DataPacket));
gch.Free();
}
}

用法:

DataPacket packet;
packet.Id = 1234;
packet.Name = "Marvin the paranoid robot";
packet.Grade = 9.2;

// serialize
var bytes = packet.Serialize();

// send via tcp
var tcp = new TcpClient(...);
tcp.GetStream().Write(bytes, 0, bytes.Length);


// deserializing;
DataPacket receivedPacket;
receivedPacket.Deserialize(bytes);

您已经有了数据包,现在您需要处理接收器上的数据包接收。这部分你不需要全部手工完成,你可以使用一些工具,就像@jgauffin 说的。

关于c# - 如何以二进制帧格式发送数据(TCP),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11969993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com