я сделал немного чтения в программировании клиента/сервера в c#. я достаточно знаком с этим процессом для выяснения у следующего вопроса:
как я передаю объекты структуры через tcp/ip вместо просто строк?
мое приложение является сетевой игрой с возможностями чата. таким образом вместо того, чтобы просто передать текст, я хотел бы к imploy структуру данных или структуру класса, которая будет иметь два поля: i. тип пакета ii. данные для типа пакета
и я передал бы это при необходимости во время выполнения приложения, и декодировать объект данных в принимающем конце и помещать его, где это принадлежит.
Я не ищу код, просто некоторые идеи и поисковые операторы, которые я могу подать к Google, таким образом, я буду; имейте лучшее понимание.
я читал о serialisation/de сериализации, то, что он способ пойти?
спасибо.
я проверил сообщения, которые обнаружились как связанные темы, но все еще хотели бы дальнейшее руководство.
Вы можете создать NetworkStream на основе Socket и использовать любой механизм Stream для передачи ваших данных. Это переводит ваш вопрос на: Как я могу читать / записывать структуру из / в Stream.
Вы можете использовать сериализацию, а также BinaryWriter / BinaryReader. Для небольшой структуры (как вы описываете) я бы написал несколько специальных методов:
var netStream = new NetworkStream(clientSocket, true);
var writer = new BinaryWriter(netStream);
writer.Write(data.Value1);
writer.Write(data.Value2);
Для больших структур я бы рассмотрел вариант Cheeso Marshaling.
Если вам не нужны все возможности сериализации - если вы просто хотите записать структуру в массив байтов, рассмотрите класс Marshal.
Например, рассмотрим приложение tar на C #. Формат tar основан на 512-байтовых блоках, и первый блок в серии имеет регулярную структуру. В идеале приложение хочет просто преобразовать данные из файла на диске, прямо в структуру . Это делает метод 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.
Тогда вот общий класс, который выполняет копирование.
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;
}
}
Вы можете использовать этот класс с любой структурой . Вы должны использовать LayoutKind.Sequential и ограничиться непреобразуемыми типами (в основном примитивами и их массивами), чтобы использовать этот подход. Это быстро и эффективно, с точки зрения кода, производительности и памяти, но он немного ограничен в том, как его можно использовать.
Получив массив байтов, вы можете передать его через NetworkStream или т. Д., А затем выполнить десериализацию с использованием того же класса на другом конце.
Сериализация - это самый простой способ, поскольку система поддерживает ее напрямую. Однако есть некоторые проблемы с производительностью с большими и сложными объектами. В вашем случае похоже, что сериализация - это путь. Если вы хотите что-то более низкого уровня, вы можете проверить BinaryWriter / BinaryReader, который позволяет вам выполнять работу самостоятельно.
Двоичная сериализация .NET, вероятно, будет самой быстрой готовой опцией, если предположить, что обе стороны механизма связи - это C # и могут загружать одну и ту же сборку, содержащую типы сообщений. Свертывание собственной сериализации, вероятно, вполне нормально, если ваши структуры очень простые. Просто определите свою структуру данных в классе, а также метод для ее преобразования в строку и из нее.
Вы на правильном пути, используя сериализацию объектов.
Одна вещь, о которой я еще не упоминал, - это то, что двоичные сериализаторы обычно создают меньше байтов для отправки через сокет, однако если вы используете сериализатор XML или JSON, а затем сжимаете результаты с помощью CompressionStream (GZipStream?), Прежде чем отправить его по сетевому потоку, вы можете получить даже меньшие размеры в зависимости от типа данных в вашем объекте (это лучше всего работает, когда у вас много строк).
Это займет больше процессорного времени для отправки и чтения сообщений, так что это компромисс, если вам нужно снизить требования к пропускной способности.
В конечном итоге да: вы говорите о сериализации. Это может принимать разные формы, особенно в .NET, но в конечном итоге вам нужно выбирать между:
My.Namespace.FooBar
). Это действительно упрощает работу, но редко работает между разными платформами (и часто не между версиями) - и вся эта информация о типах может быть подробной Подходы к ручному сериализатору включают (просто упоминая ключевое слово "сериализатор"): TextWriter
, XmlWriter
, IXmlSerializable
, BinaryWriter
, ISerializable
. Вы не хотите этого делать ...
Сосредоточение внимания на автоматических сериализаторах:
| Contract | Metadata
===============+========================+===========================
Text | XmlSerializer | SoapFormatter
| DataContractSerializer | NetDataContractSerializer
| Json.NET |
---------------+------------------------+---------------------------
Binary | protobuf-net | BinaryFormatter
Поскольку вы говорите о необработанных потоках, я бы предпочел двоичный сериализатор на основе контрактов - но тогда я написал protobuf-net , поэтому я могу быть предвзятым ;-p
Для сравнения с обычными стеками RPC:
BinaryFormatter
XmlSerializer
DataContractSerializer
или NetDataContractSerializer
,