Send objects via Sockets - c#

I am new to stocks in C#, I wish to send a Object in C#. Have been using BinaryWriter to send data (works fine for string), but it doesn't seem to have a method like
writer.Writer(new SerliaizedObject());
How do we achieve this using BinaryReader/BinaryWriter
UPDATE:
I used the following functions to convert by object to byte and send it across to the client
public static byte[] SerializeToBytes<T>(T item)
{
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, item);
stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
}
}
public static object DeserializeFromBytes(byte[] bytes)
{
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream(bytes))
{
return formatter.Deserialize(stream);
}
}
To send the data is used:
formatter = new BinaryFormatter();
MessageBox.Show(SerializeToBytes<mydata>(new mydata()).Length+"");
writer.Write(SerializeToBytes<mydata>(new mydata()));
ChatBox.AppendText("Client Says :" + UserMessage.Text + "\r\n");
And to read the data I used:
while (true)
{
byte[] bytes = reader.ReadBytes(120);
mydata temp = DeserializeFromBytes(bytes) as mydata;
ChatBox.AppendText("Server Says " + temp + "\r\n");
}
But the reader doesn't seem to work, Any Ideas?

Use BinaryFormatter to write serializable objects to streams in binary format:
FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, mySerializable);

You should use the first 4 bytes as length header, and in the receive loop you add a variable bytesReadSoFar. Then you know when everything is received.

Related

I am getting a "system.runtime.serialization.serializationexception" when using the binary formatter

private byte[] ToByteArray(Message msg)
{
if(msg == null)
{
return null;
}
BinaryFormatter bf = new BinaryFormatter();
using(MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, msg);
return ms.ToArray();
}
}
private Message ToMessageObject(Byte[] bytes)
{
if(bytes == null)
{
return null;
}
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(bytes))
{
ms.Write(bytes, 0, bytes.Length);
ms.Position = 0;
Message msg = (Message)bf.Deserialize(ms);
return msg;
}
}
I am using the two above methods for serialization and deserialization, but it keeps on throwing the error during deserializaion.
system.runtime.serialization.serializationexception: 'end of stream encountered before parsing was completed.'
My message class has the "Serializable" attribute.
One of the things I noticed is when the text is small, like two words, it deserializes fine but when it contains a lot of characters, close to 100, that's when I get that error. I have been checking other solutions()frome here and other places to this problem but none seems to work for me.
From the comments, I was able to figure out that the problem was caused by the initialization of the byte array,
var responseStream = client.GetStream()
var bytes = new byte[1024];
if (responseStream.DataAvailable)
{
await responseStream.ReadAsync(bytes, 0, bytes.Length);
var responseMessage =ToMessageObject(bytes);
messages.Add(responseMessage);
}
Initially, I set the bytes array length to 256. The error was thrown anytime I had to deserialize a byte array of length greater than 256. So, I am wondering if it's possible to use a dynamic array when reading from a stream.

binary serialization to list

I used this information to convert a list to .txt with binary serialization. now I want to load that file, and put it again in my list.
this is my code to convert a list to .txt with binary serialization:
public void Save(string fileName)
{
FileStream fs = new FileStream(#"C:\" + fileName + ".txt", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, list);
fs.Close();
}
so my question is; how to convert this binary file back to a list?
You can do it like this:
//Serialize: pass your object to this method to serialize it
public static void Serialize(object value, string path)
{
BinaryFormatter formatter = new BinaryFormatter();
using (Stream fStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
{
formatter.Serialize(fStream, value);
}
}
//Deserialize: Here is what you are looking for
public static object Deserialize(string path)
{
if (!System.IO.File.Exists(path)) { throw new NotImplementedException(); }
BinaryFormatter formatter = new BinaryFormatter();
using (Stream fStream = File.OpenRead(path))
{
return formatter.Deserialize(fStream);
}
}
Then use these methods:
string path = #"C:\" + fileName + ".txt";
Serialize(list, path);
var deserializedList = Deserialize(path);
Thanks #Hossein Narimani Rad , I used your answer and changed it a bit (so I understand it more) and now it works.
my binair serialize method (save) is still the same.
this is my binair deserialize method (load):
public void Load(string fileName)
{
FileStream fs2 = new FileStream(fileName, FileMode.Open);
BinaryFormatter binformat = new BinaryFormatter();
if (fs2.Length == 0)
{
MessageBox.Show("List is empty");
}
else
{
LoadedList = (List<Object>)binformat.Deserialize(fs2);
fs2.Close();
List.Clear();
MessageBox.Show(Convert.ToString(LoadedList));
List.AddRange(LoadedList);
}
I know I don't have an exception now, but I understand it better this way.
I also added some code to fill my listbox with my List with the new LoadedList.

Serialize object into string

I am trying to serialize a class to be sent to a server where the server will use that object. I am using Microsoft's example of an asynchronous client/server setup for this: http://msdn.microsoft.com/en-us/library/bew39x2a.aspx I am using the binary formatter.
To test this, I am using this class:
[Serializable]
class Class1
{
public int x = 10;
public string banana = "banana";
}
and attempting to serialize it with:
Class1 example = new Class1();
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
formatter.Serialize(stream, example);
in order to send it to the server, I need to send a string:
StreamReader reader = new StreamReader( stream );
string text = reader.ReadToEnd();
server.Send(text);
stream.Close();
but this doesn't work. I have tried converting the stream to a byte[] as seen here but I keep getting a Stream was unreadable exception when testing this in the debugger.
Try
Class1 example = new Class1();
IFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, example);
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
String text = sr.ReadToEnd();
server.Send(text);
}
I think that the part that got missed is resetting the position of MemoryStream to be able to read (think of it as rewinding for playback after recording)

Stream.WriteTo locks up thread

I have this code:
public static void SerializeRO(Stream stream, ReplicableObject ro) {
MemoryStream serializedObjectStream = new MemoryStream();
Formatter.Serialize(serializedObjectStream, ro);
MemoryStream writeStream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(writeStream);
bw.Write(serializedObjectStream.Length);
serializedObjectStream.Seek(0, SeekOrigin.Begin);
serializedObjectStream.WriteTo(writeStream);
serializedObjectStream.Close();
writeStream.WriteTo(stream);
bw.Close();
}
The line writeStream.WriteTo(stream); never finishes. The program gets to that line and won't progress.
stream is always a NetworkStream. I've checked and I think it's a valid object (at least it's not null nor disposed).
So what's going on?
I tried your code - writing to a FileStream - and I always get zero bytes written to the stream. I don't know why WriteTo would block on a NextWorkStream when there's nothing to write, but that could be a problem
When I extract the bytes from the MemoryStream and write them directly to stream everything works e.g. (I'm creating a binary formatter in the routine, it seems you already have a formatter).
public static void SerializeRO(Stream stream, object ro)
{
MemoryStream serializedObjectStream = new MemoryStream();
var f = new BinaryFormatter();
f.Serialize(serializedObjectStream, ro);
MemoryStream writeStream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(writeStream);
var bytes = serializedObjectStream.ToArray();
bw.Write(bytes.Length);
bw.Write(bytes);
var bwBytes = writeStream.ToArray();
stream.Write(bwBytes, 0, bwBytes.Length);
bw.Close();
}
However I'd do it like this with one MemoryStream and writing directly to stream, unless there's something I don't know about NetworkStream (this will of course close stream which may not be what you want)
public static void SerializeRO(Stream stream, object ro)
{
byte[] allBytes;
using (var serializedObjectStream = new MemoryStream())
{
var f = new BinaryFormatter();
f.Serialize(serializedObjectStream, ro);
allBytes = serializedObjectStream.ToArray();
}
using (var bw = new BinaryWriter(stream))
{
bw.Write(allBytes.Length);
bw.Write(allBytes);
}
}
Version that won't close your NetworkStream (just don't put the binary writer in a using statement or Close() it)
public static void SerializeRO(Stream stream, object ro)
{
byte[] allBytes;
using (var serializedObjectStream = new MemoryStream())
{
var f = new BinaryFormatter();
f.Serialize(serializedObjectStream, ro);
allBytes = serializedObjectStream.ToArray();
}
var bw = new BinaryWriter(stream)
bw.Write(allBytes.Length);
bw.Write(allBytes);
}
Just my thoughts: try to close your BinaryWriter before writing stream to another. While your writer is opened stream is not finished and as the result WriteTo newer will find the end of the stream.

"Binary stream does not contain a valid BinaryHeader" error on (de)serialization?

I am created a post before " Object to byte not working " .
I fixed problems that users said me , but there is still problem .
Error Message : The constructor to deserialize an object of type 'WindowsFormsApplication1.Form1+Item' was not found.;
void start()
{
Item item = new Item();
item.files.Add(#"test");
byte[] b = ObjectToByteArray(item);
Item k = Desriles(b);
}
[Serializable]
public class Item : ISerializable
{
public Item()
{
files = new List<string>();
Exclude = false;
CleanEmptyFolder = false;
}
public List<string> files;
public string MusicProfileName;
public bool Exclude;
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("files", files);
info.AddValue("MusicProfileName", MusicProfileName);
info.AddValue("Exclude", Exclude);
}
#endregion
}
public byte[] ObjectToByteArray(object _Object)
{
using (var stream = new MemoryStream())
{
// serialize object
var formatter = new BinaryFormatter();
formatter.Serialize(stream, _Object);
// get a byte array
var bytes = new byte[stream.Length];
using (BinaryReader br = new BinaryReader(stream))
{
bytes = br.ReadBytes(Convert.ToInt32(stream.Length));
}
return bytes;
}
}
public Item Desriles(byte[] items)
{
using (MemoryStream stream = new MemoryStream())
{
stream.SetLength(items.LongLength);
stream.write(items, 0, items.Length);
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object item = formatter.Deserialize(stream); // Here I will get error
return (Item)item;
}
}
The serialization code can't work properly, you forgot to reset the stream back to the beginning. The better mouse trap:
public byte[] ObjectToByteArray(object _Object) {
using (var stream = new MemoryStream()) {
var formatter = new BinaryFormatter();
formatter.Serialize(stream, _Object);
return stream.ToArray();
}
}
The deserialization code can similarly be simplified:
public Item Desriles(byte[] items) {
using (MemoryStream stream = new MemoryStream(items)) {
var formatter = new BinaryFormatter();
return (Item)formatter.Deserialize(stream);
}
}
And you don't need GetObjectData().
In this section:
using (MemoryStream stream = new MemoryStream())
{
stream.SetLength(items.LongLength);
stream.Read(items, 0, items.Length);
[...]
object item = formatter.Deserialize(stream);
it seems you are creating a new, empty memory stream, then attempting to read from it, and Deserialize from it.
Of course it fails. The stream is empty.
abelenky makes a good point, but I don't think your:
public byte[] ObjectToByteArray(object _Object)
works either.
C# Code Snippet - Object to byte array
C# Code Snippet - Byte array to object
Thanks to All :
I found problem : I should base that to ISerializable

Categories

Resources