PDA

View Full Version : حرفه ای: تبديل ارايه اي از نوع بايت به استراكت.



hunter_ara
یک شنبه 24 مهر 1390, 12:05 عصر
سلام دوستان ميخواستم بدونم چطور ميشه ارايه اي از نوع بايت رو به استراكت تبديل كرد.
توي برنامه ي كلاينت ميام با استفاده از اين تابع يه استراكت رو به بايت تبديل ميكنم و از طريق اينترنت ميفرستمش براي سرور.
ميخوام تو سرور برش گردونم به حالت اول.
public static byte[] Serialize(object obj)
{
Type objectType = obj.GetType();
int objectSize = Marshal.SizeOf(obj);
IntPtr buffer = Marshal.AllocHGlobal(objectSize);
Marshal.StructureToPtr(obj, buffer, false);
byte[] array = new byte[objectSize];
Marshal.Copy(buffer, array , 0, objectSize);
Marshal.FreeHGlobal(buffer);
return array;
}

mehdi.mousavi
یک شنبه 24 مهر 1390, 14:15 عصر
سلام.
آیا دلیلی داره که بدین شکل دارید Structure رو Serialize می کنید؟ روش ساده تری که نیاز به استفاده از Marshaling و Allocate کردن حافظه بصورت دستی توسط برنامه نویس نداره، این هستش که از BinaryFormatter استفاده کنید. برای اینکار، ابتدا کلاسی زیر رو به پروژه اضافه کنید:


using System;
using System.IO;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;

namespace Whatever
{
public static class BinarySerializer<T>
{
public static byte[] Serialize(T graph)
{
if (graph == null)
throw new ArgumentNullException("graph");

using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter fmt = new BinaryFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple };
fmt.Serialize(ms, graph);
return ms.ToArray();
}
}

public static T Deserialize(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");

if (data.Length == 0)
throw new ArgumentException("Attempting to deserialize an empty stream!", "data");

using (MemoryStream ms = new MemoryStream(data, false))
{
BinaryFormatter fmt = new BinaryFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple };
return (T)fmt.Deserialize(ms);
}
}
}
}

به اون AssemblyFormat ای که Set کرده ام دقت کنید. اون Flag باعث میشه تا داده های Serialize شده بدون توجه به Assembly ی مربوطه، قابل Deserialize شدن باشن. حالا فرض کنیم Structure ای داریم بدین شکل (اینجا هم به Serializable Attribute دقت کنید):


[Serializable]
public struct MyStruct
{
public int Field1;
public string Field2;
}

و Instance ای از اون داریم:

MyStruct st = new MyStruct { Field1 = 2, Field2 = "test" };

برای تبدیل st به byte array، کافیه بدین شکل عمل کنیم:

byte[] bytes = BinarySerializer<MyStruct>.Serialize(st);

و برای Deserialize کردن اون byte array در سمت دیگه، می تونیم بدین شکل عمل کنیم:

MyStruct st2 = BinarySerializer<MyStruct>.Deserialize(bytes);

موفق باشید.

hunter_ara
یک شنبه 24 مهر 1390, 14:45 عصر
سلام.
آیا دلیلی داره که بدین شکل دارید Structure رو Serialize می کنید؟ روش ساده تری که نیاز به استفاده از Marshaling و Allocate کردن حافظه بصورت دستی توسط برنامه نویس نداره، این هستش که از BinaryFormatter استفاده کنید. برای اینکار، ابتدا کلاسی زیر رو به پروژه اضافه کنید:


using System;
using System.IO;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;

namespace Whatever
{
public static class BinarySerializer<T>
{
public static byte[] Serialize(T graph)
{
if (graph == null)
throw new ArgumentNullException("graph");

using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter fmt = new BinaryFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple };
fmt.Serialize(ms, graph);
return ms.ToArray();
}
}

public static T Deserialize(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");

if (data.Length == 0)
throw new ArgumentException("Attempting to deserialize an empty stream!", "data");

using (MemoryStream ms = new MemoryStream(data, false))
{
BinaryFormatter fmt = new BinaryFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple };
return (T)fmt.Deserialize(ms);
}
}
}
}

به اون AssemblyFormat ای که Set کرده ام دقت کنید. اون Flag باعث میشه تا داده های Serialize شده بدون توجه به Assembly ی مربوطه، قابل Deserialize شدن باشن. حالا فرض کنیم Structure ای داریم بدین شکل (اینجا هم به Serializable Attribute دقت کنید):


[Serializable]
public struct MyStruct
{
public int Field1;
public string Field2;
}

و Instance ای از اون داریم:

MyStruct st = new MyStruct { Field1 = 2, Field2 = "test" };

برای تبدیل st به byte array، کافیه بدین شکل عمل کنیم:

byte[] bytes = BinarySerializer<MyStruct>.Serialize(st);

و برای Deserialize کردن اون byte array در سمت دیگه، می تونیم بدین شکل عمل کنیم:

MyStruct st2 = BinarySerializer<MyStruct>.Deserialize(bytes);

موفق باشید.

مرسي كه جواب دادين.
خودم هم ميخواستم از BinaryFormatter استفاده كنم ولي چون كلاينت ويندوز موبايل هست Compact Framework ساپورتش نميكنه.
حالا امكانش هست كه Deserialize
كردن رو از همين طريق كه خودم انجام دادم راهنماييم كنيد؟؟؟؟
سرور C#
و كنسول هست. :خجالت::خجالت::خجالت::خجالت:: جالت::خجالت::خجالت::خجالت:

mehdi.mousavi
یک شنبه 24 مهر 1390, 15:26 عصر
حالا امكانش هست كه Deserialize كردن رو از همين طريق كه خودم انجام دادم راهنماييم كنيد؟؟؟؟ سرور C#‎‎ و كنسول هست.

سلام.
چرا که نه... کافیه بدین روش عمل کنید:

MyStruct GetMyStruct(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
MyStruct st = (MyStruct)Marshal.PtrToStructure(handle.AddrOfPinn edObject(), typeof(MyStruct));
handle.Free();
return st;
}

(البته من برای MyStruct خودم اینو نوشتم، شما باید اونو به Structure خودتون تغییر بدید).

موفق باشید.

hunter_ara
سه شنبه 26 مهر 1390, 11:58 صبح
سلام.
چرا که نه... کافیه بدین روش عمل کنید:

MyStruct GetMyStruct(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
MyStruct st = (MyStruct)Marshal.PtrToStructure(handle.AddrOfPinn edObject(), typeof(MyStruct));
handle.Free();
return st;
}

(البته من برای MyStruct خودم اینو نوشتم، شما باید اونو به Structure خودتون تغییر بدید).

موفق باشید.
خيلي ممنونم از كمكتون ولي راستش من تازه كارم و خيلي تجربه ندارم.
ميشه بگيد چطور ميتونم بايت هايي كه از NetworkStream ميگيرم رو به اين تابع بدم تا تبديل كنه؟؟؟

اون وقت تو اين كد شما اومدين يه تابع نوشتين از نوع Structure ؟؟؟؟

كد سرور اينه ولي نميتونم اين تابع رو داخلش Call كنم.
namespace OurSpiffyServer_ConsoleApp
{
class Program
{
const int Port = /*a local port number*/; // The port number we're going to listen on. Any unused port < 65534 preferably above 1024 (protected ports)
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Data
{
//public int id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string Send;
}
//rebuilding structure
Data GetMyStruct(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
Data dt = (Data)Marshal.PtrToStructure(handle.AddrOfPinnedOb ject(), typeof(Data));
handle.Free();
return dt;
}
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Blue;
Console.Clear();
// Our local IP address - you'll be wanting to change this...
try
{
System.Net.IPAddress serverAddress = System.Net.IPAddress.Parse(/*my server adress*/); // <-- Change that as appropriate!

// Start listening for connections on our IP address + Our Port number
TcpListener listener = new TcpListener(serverAddress, Port);
listener.Start();
Console.WriteLine("Server is waiting on port '6394'...");

// Is someone trying to call us? Well answer!
TcpClient TCP_Client = listener.AcceptTcpClient();
Console.WriteLine("Client connected");

//A network stream object. We'll use this to send and receive our data, so create a buffer for it...
NetworkStream ourStream = TCP_Client.GetStream();
byte[] ReceivedData = new byte[TCP_Client.ReceiveBufferSize];
GetMyStruct(ReceivedData);
// read the incoming data stream - note that Read() is a blocking call...
int bytesRead = ourStream.Read(ReceivedData, 0, System.Convert.ToInt32(TCP_Client.ReceiveBufferSiz e));
// echo the data we got to the console until the newline, and delay closing our window.

Console.WriteLine("Received : "/*Encoding.UTF8.GetString(data, 0, bytesRead)*/);
Console.ReadKey();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadKey();
}
}
}
}
اگر راهنماييم كنيد خيلي ممنون ميشم. :خجالت::خجالت::خجالت::خجالت:

hunter_ara
شنبه 30 مهر 1390, 09:18 صبح
دوستان ميشه خواهش كنم كه جواب سوالم رو بديد.
الان به خاطر اين مشكل نزديك 4 روزه كه هيچ پيشرفتي نداشتم.
جدا از بحث كار يادگيري هم مهمه ها!!!!!
لطف ميكنيد جواب بديد.