IOException thrown by BinaryFormatter.Deserialize

G

Guest

Hi,

When I'm doing BinaryFormatter.Deserialize() over a TCP socket. When I'm
closing the TcpListener by invoking the TcpListener.Stop(); I get:

System.IO.IOException with message "Unable to read data from the transport
connection." that InnerException of type System.Net.Sockets.SocketException
saying "An established connection was aborted by the software in your host
machine".

The code I'm using is (it's not the complete code because the complete code
is very long and threaded):
-------------------------------------------------------------
string serverIP = "some IP address";
int port = 3001;

TcpListener m_server;
m_server = new TcpListener( System.Net.IPAddress.Parse(serverIP), port );

Socket m_socket = m_server.AcceptSocket();

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

while( true )
{
NetworkStream networkStream = new NetworkStream(m_socket);
MyObjectType obj = formatter.Deserialize(networkStream) as MyObjectType;
// throw the IOException when the TcpListener is closed by TcpListener.Stop();
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Must probably it's cause the networkstream ends without further notice (
probably cause the client sent all the data and closed the connection ) .

Try to do this, copy the networkstream to a memorystream, later deserialize
from that memory stream.

Do you by any chance send the size first?


cheers,
 
G

Guest

Thanks Ignacio,

The client (the side that does the Serialize) is not closing the socket.
The IOException is thrown when I'm doing the stop on the server side (the
side that does the Deserialize).

The while loop is already Deserialized 30 MyObjectType objects, and this all
the objects that has been Serialized to the socket on the other side.

Can you post a sample code explaining what you want me to check?

No, I'm not sending any size first, I simply doing this:

string serverIP = "The server IP";
int port = 3001;
Socket m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
System.Net.IPEndPoint ep = new
System.Net.IPEndPoint(System.Net.IPAddress.Parse(serverIP ), port);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
NetworkStream networkStream = new NetworkStream(m_socket);
foreach( MyObjectType obj in myObjectTypeList )
{
formatter.Serialize(networkStream, obj);
}
// waiting...


Any idea?
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

I had a similar situation, the problem it seems that the client send the
data and just close the connection, sometimes even without sending all the
data, ( there is a property of TcpClient.LingerState that control this) and
the server side was reporting the same error you are seeing.

Do this test, use a memorystream to read the data , use
NetworkStream.DataAvailable , see the example in the help, or you could just
read a byte at a time:

MemoryStream mem = new MemoryStream()
int b=-1;
while( (b=networkstream.ReadByte()) != -1 )
mem.WriteByte( (byte)b);


cheers,
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

An extra question, you said that it already had 30 objects deserialized ,
how many are you sending? 31?


cheers,
 
G

Guest

Hi Ignacio,

That's exactly the point, I'm Serialize 30 objects and getting them all at
the deserializing side.
So all the data was sent successfully.
But still I get this exception when closing the TcpListener.

What do you think.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi Sharon,

I have a similar problem

DO this, Check the InnerException to see what it contains, if so what is
the ErrorCode you are getting?

cheers,
 
G

Guest

Hi Ignacio,

Ok,
The top exception is System.IO.IOException {"Unable to read data from the
transport connection."}, and it contains an inner exception
System.Net.Sockets.SocketException {"An established connection was aborted by
the software in your host machine"}

NativeErrorCode = 10053

Stack trace:

System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
System.IO.Stream.ReadByte()
at System.IO.BinaryReader.FillBuffer(Int32 numBytes)
System.IO.BinaryReader.ReadByte()
System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadByte(
System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input
System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord()
System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler
handler, __BinaryParser serParser, Boolean fCheck, IMethodCallMessage
methodCallMessage)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream
serializationStream, HeaderHandler handler, Boolean fCheck,
IMethodCallMessage methodCallMessage
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)


I hope it gives you what you need.
 
P

Peter Huang [MSFT]

Hi

Here is a KB may related with your problem.

PRB: TcpClient Close Method Does Not Close the Underlying TCP Connection
http://support.microsoft.com/?id=821625


Also I suggest you try to use the syntax something like below to receive
the network stream.


[pseudocode]
try
{
Int32 port = 13000;
TcpListener server = new TcpListener(port);
server.Start();
Byte[] bytes = new Byte[256];
while(true)
{
Console.Write("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
NetworkStream stream = client.GetStream();
Int32 i;
int pos=0;
MemoryStream ms = new MemoryStream();
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
ms.Write(bytes,pos,i);
pos +=i;
}
stream.Close();
client.Close();
}
}
catch(SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
//Handle the Deserial here.
Console.WriteLine("\nHit enter to continue...");
Console.Read();
//Close the listener.
tcpListener.Stop();
}


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Peter Huang [MSFT]

Hi Sharon,

Thanks very much for your detailed information.
From your description, it seems that you have a multiple thread in your
application.
Also BinaryFormatter.Deserialize Method is used to Deserializes a stream
into an object graph.
public virtual object Deserialize(Stream);
The Steam can only only be a NetworkStream, but also a MemoryStream. What
we do is just to copy the NetworkStream content into MemoryStream, and then
call the Deserialize on memory stream.
So far can you send a simple sample for your scenario as long as it can
reproduce the problem.
You can reach me via removing the "online" from my email address.

Thanks for your efforts.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Peter Huang [MSFT]

Hi Sharon,

Firstly I am glad that it seems that you have fixed the exception problem.
As for your another question about the performance about the TCPClient and
Socket approach, I think they did not make difference.
The TCPClient is a wrap for socket class so that we can use it more easier,
in the low level, it is still using Socket.
If you use reflector to disassembly the .NET code you will find the
GetStream similar with below.
You will find that it will create the NetworkStream inside.

You can get the Reflector tool in the link below.
http://www.aisto.com/roeder/dotnet/

public NetworkStream GetStream()
{
if (this.m_CleanedUp)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
if (!this.Client.Connected)
{
throw new
InvalidOperationException(SR.GetString("net_notconnected"));
}
if (this.m_DataStream == null)
{
this.m_DataStream = new NetworkStream(this.Client,
true);//////////////////////////////////////////////// this.Client is
Socket instance.
this.m_DataStreamCreated = true;
}
return this.m_DataStream;
}


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Peter Huang [MSFT]

Hi Sharon,

How is the things going?
If you still have any concern on this issue, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top