我在c#中用客户端/服务器编程做了一些阅读.我对这个过程非常熟悉,可以提出以下问题:
我如何通过tcp/ip而不仅仅是字符串传输结构对象?
我的应用程序是一个具有聊天功能的联网游戏.所以我不想只传输文本,而是想要构建一个包含两个字段的数据结构或类结构:i.包类型ii.数据包类型的数据
我会在应用程序执行期间需要时传输它,并在接收端解码数据对象并将其放在它所属的位置.
我不寻找代码,只是一些想法和搜索语句,我可以提供给谷歌,所以我会; 有一个更好的理解.
香港专业教育学院阅读有关序列化/反序列化,是他的方式去?
谢谢.
我已经检查了相关主题但仍然需要进一步指导的帖子.
最终是的:你在谈论序列化.这可以采用多种形式,尤其是在.NET中,但最终您需要选择:
My.Namespace.FooBar
实例).这使得它很容易工作,但很少在不同平台之间工作(通常不在版本之间) - 并且所有类型信息可能很冗长手册串行方法包括(只提的是"串行"关键字): ,TextWriter
,XmlWriter
,IXmlSerializable
,.BinaryWriter
ISerializable
你不想这样做......
更多关注自动序列化器:
| Contract | Metadata
===============+========================+===========================
Text | XmlSerializer | SoapFormatter
| DataContractSerializer | NetDataContractSerializer
| Json.NET |
---------------+------------------------+---------------------------
Binary | protobuf-net | BinaryFormatter
Run Code Online (Sandbox Code Playgroud)
既然你在谈论原始流,我的偏好是基于二进制契约的序列化器 - 但是,我写了protobuf-net,所以我可能有偏见;-p
与常见的RPC堆栈进行比较:
BinaryFormatter
XmlSerializer
DataContractSerializer
或者NetDataContractSerializer
有时XmlSerializer
(它也可以配置为使用例如protobuf-net)我可以愉快地编写一个在流上使用protobuf-net来表示不同类型的不同消息的示例,但是使用protobuf-net的套接字处理的一个简单示例是在其中一个示例项目中(事实上,这里)
如果您不需要丰富的序列化 - 如果您只想将结构写入字节数组,请考虑Marshal类.
例如,考虑C#中的tar应用程序.tar格式基于512字节块,并且系列中的第一个块具有规则结构.理想情况下,应用程序要公正blitt从磁盘文件中的数据,右转入结构.该Marshal.PtrToStructure方法做到这一点.这是结构.
[StructLayout(LayoutKind.Sequential, Size=512)]
internal struct HeaderBlock
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public byte[] name; // name of file.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] mode; // file mode
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] uid; // owner user ID
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] gid; // owner group ID
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] size; // length of file in bytes
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] mtime; // modify time of file
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] chksum; // checksum for header
// ... more like that... up to 512 bytes.
Run Code Online (Sandbox Code Playgroud)
然后这是一个执行blitting的泛型类.
internal class RawSerializer<T>
{
public T RawDeserialize( byte[] rawData )
{
return RawDeserialize( rawData , 0 );
}
public T RawDeserialize( byte[] rawData , int position )
{
int rawsize = Marshal.SizeOf( typeof(T) );
if( rawsize > rawData.Length )
return default(T);
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.Copy( rawData, position, buffer, rawsize );
T obj = (T) Marshal.PtrToStructure( buffer, typeof(T) );
Marshal.FreeHGlobal( buffer );
return obj;
}
public byte[] RawSerialize( T item )
{
int rawSize = Marshal.SizeOf( typeof(T) );
IntPtr buffer = Marshal.AllocHGlobal( rawSize );
Marshal.StructureToPtr( item, buffer, false );
byte[] rawData = new byte[ rawSize ];
Marshal.Copy( buffer, rawData, 0, rawSize );
Marshal.FreeHGlobal( buffer );
return rawData;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将该类与任何结构一起使用.您必须使用LayoutKind.Sequential并将自己限制为blittable类型(基本上是基元和相同的数组)才能使用此方法.它在代码,性能和内存方面快速而有效,但它在如何使用方面受到一定限制.
获得字节数组后,可以通过NetworkStream等传输它,然后在另一端使用相同的类进行反序列化.
序列化是最简单的方法,因为系统直接支持它.但是,对于大而复杂的对象存在一些性能问题.在你的情况下,听起来像序列化是要走的路.如果您想要更低级别的东西,您可以查看BinaryWriter/BinaryReader,它允许您自己完成工作.
您可以基于 Socket 创建 NetworkStream,并使用任何 Stream 机制来传输数据。这将您的问题转化为:我如何从流中读取/写入结构。
您可以使用序列化,也可以使用 BinaryWriter/BinaryReader。对于一个小结构(如您所描述的),我会编写一些自定义方法:
var netStream = new NetworkStream(clientSocket, true);
var writer = new BinaryWriter(netStream);
writer.Write(data.Value1);
writer.Write(data.Value2);
Run Code Online (Sandbox Code Playgroud)
对于较大的结构,我会考虑 Cheeso 的编组选项。
归档时间: |
|
查看次数: |
18263 次 |
最近记录: |