Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Thursday, January 28, 2016 11:36 PM
Hi, I am having a very big problem with serializing.
NetPacket message = (NetPacket)this.bf.Deserialize(ns);
The top line gives me a bad error,
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: The input stream is not a valid binary format. The starting contents (in bytes) are: 00-FF-FF-FF-FF-00-00-00-00-02-00-00-00-4E-65-74-77 ...
I really do not know why. I am new to networking and the concept of binary data.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace NetworkLibraryFoo
{
[Serializable]
public class NetPacket
{
public int Type { get; set; }
public string Message { get; set; }
public string Name { get; set; }
public static void SentToSocket(NetworkStream ns, NetPacket np)
{
BinaryFormatter formatter = new BinaryFormatter(); // the formatter that will serialize my object on my stream
formatter.Serialize(ns, np); // the serialization process
}
public static NetPacket ReadPacket(NetworkStream ns)
{
BinaryFormatter formatter = new BinaryFormatter();
ns.Seek(0, SeekOrigin.Begin);
NetPacket np = (NetPacket)formatter.Deserialize(ns);
return np;
}
}
}
The top class is a library that the server and client have. This means they will understand the object that is sent.
public Form2(Socket client, string userName) : this(client)
{
InitializeComponent();
this.client = client;
Thread t = new Thread(Listen);
//t.Start();
textBoxEnterText.ScrollBars = ScrollBars.Vertical;
this.userName = userName;
NetworkStream ns = new NetworkStream(this.client);
NetPacket np = new NetPacket();
np.Name = this.userName;
NetPacket.SentToSocket(ns, np);
}
The Top code is the client constructor. The client sends this to the server.
public HandleClient(Socket client)
{
this.client = client;
Program.socketList.Add(this.client);
Console.WriteLine("I have a client");
listenForMessageThread = new Thread(listenForMessage);
listenForMessageThread.Start();
NetPacket np1 = new NetPacket();
NetworkStream ns = new NetworkStream(client);
// np1 = NetworkLibraryFoo.NetPacket.ReadPacket(ns);
Thread.Sleep(1000);
NetPacket message =
(NetPacket)this.bf.Deserialize
(ns);
Console.WriteLine(message.Name);
Console.Read();
// Console.WriteLine(name + " logged in");
}
This is the server code, where it gets the info from client. But it crashes here.
Anyone know why?
All replies (4)
Monday, February 1, 2016 3:15 PM âś…Answered
You're trying to use a binary formatter on the network stream and I don't believe that is going to work out. Network streams are forward only. You cannot seek in them (the CanSeek property always returns false). Since you cannot seek in them the formatter won't work (because it requires that you be at the start of the stream). You also have the problem that the stream doesn't know when it is at the end of the stream and therefore cannot be used to reliably determine how much data is available. It might be in the middle of receiving the next set of data when you read it, hence the counts are wrong.
The correct approach to reading a network stream is to read the data into a temporary buffer (stream) and then pass that to your formatter. In your case you seem to know how many bytes the message takes so you should read from the network stream until you've gotten a message worth of data, then pass that data on to the formatter.
Personally when I have to do this kind of stuff I simply serialize/deserialize the data manually using a helper method and BinaryReader/BinaryWriter.
Michael Taylor
http://blogs.msmvps.com/p3net
Friday, January 29, 2016 12:22 AM
[Serializable]
public class NetPacket
{
public int Type { get; set; }
public string Message { get; set; }
public string Name { get; set; }
}
Are saying that the above is the only thing that is to be sent between two processes is the above?
Then what is the behavior in the class about that shouldn't be there?
Maybe it should just be a simple DTO, binary serialize and send it.
https://en.wikipedia.org/wiki/Data_transfer_object
**The top class is a library that the server and client have. This means they will understand the object that is sent. **
[Serializable]
public class NetPacket
{
public int Type { get; set; }
public string Message { get; set; }
public string Name { get; set; }
}
For me, there would be a class above in a classlib project called Entities, Netpackets or anything you want to call it with no behavior in the class no methods.
And the client and server would know about that simple data transfer object, because they have set project reference to Entities, Netpackets or whatever you want to call it. The client and server would just send the simple object between them.
Monday, February 1, 2016 2:46 PM
Sorry for the late reply, I was working during the weekend.
Yeah that class is to be sent over the network stream.
Of course I will initialize the variables.
I do have project reference to Netpackets. So why is the problem still coming up?
Monday, February 1, 2016 3:05 PM
What is the role of listenForMessageThread in this process and does deserialization work if you do not start it?
Also check if client is the right socket. How is was obtained?