XmlSerializer over NetworkStream

N

Newbro

I'm developing a server client programs which handle communications between
PC and PDA devices. XmlSerializer is used to serialize Packet object and
send/receive over networkstream.

The program works just fine initially, but choke when there's a constant
stream of data coming, which cause an XmlException to be thrown with error
"There's an error in XML document (....". For example if I were to send a
chat message Packet every other 2 seconds the program will remains ok, but
will throw an XmlException error almost instantly if I were to repeatly
sending a chat message Packet.

Basically both the server and client uses the same two functions SendPacket
and ReceivePacket to send an packet object to the other party, and a thread
calling ReceivePacket every other second.

Anyone care to enlight me on this very matter would be great. Thanks.

public void SendPacket(Packet data)
{
if (data == null) return;
try
{
String xmlString = Helper.SerializePacket(data);
Byte[] buffer = Helper.StringToUTF8ByteArray(xmlString);
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();

}
catch (Exception e)
{
throw e;
}
}

public Packet ReceivePacket()
{
try
{
Byte[] buffer = new Byte[Packet._PACKET_BYTE];
int bufferSize = networkStream.Read(buffer, 0, buffer.Length);
String xmlString = Helper.UTF8ByteArrayToString(buffer);
return (Helper.DeserializePacket(xmlString));

}
catch (Exception e)
{
throw e;
}
}

/// <summary>
/// Convert a Byte array to UTF-8 encoded string
/// </summary>
/// <param name="characters">Byte array to be converted</param>
/// <returns>String representation of given byte array</returns>
public static String UTF8ByteArrayToString(Byte[] characters)
{

UTF8Encoding encoding = new UTF8Encoding();
String constructedString = encoding.GetString(characters, 0,
characters.Length);
return (constructedString);
}

/// <summary>
/// Convert a UTF-8 encoded string to Byte array
/// </summary>
/// <param name="pXmlString">String to be converted</param>
/// <returns>Byte array representation of given string</returns>
public static Byte[] StringToUTF8ByteArray(String pXmlString)
{
UTF8Encoding encoding = new UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(pXmlString);
return byteArray;
}

/// <summary>
/// Serialize a Packet object into a UTF-8 encoded string
/// </summary>
/// <param name="packetObj">Packet to be serialized</param>
/// <returns>Serialized string of given object</returns>
public static String SerializePacket(Packet packetObj)
{
try
{
String XmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(Packet));
XmlTextWriter xmlTextWriter = new
XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, packetObj);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;
}
catch (Exception e)
{
throw e;
}
}

/// <summary>
/// Deserialize a string into Packet object
/// </summary>
/// <param name="xmlString">String to be deserialized</param>
/// <returns>Packet object of the given string</returns>
public static Packet DeserializePacket(String xmlString)
{
try
{
XmlSerializer xs = new XmlSerializer(typeof(Packet));
MemoryStream memoryStream = new
MemoryStream(StringToUTF8ByteArray(xmlString));
XmlTextWriter xmlTextWriter = new
XmlTextWriter(memoryStream, Encoding.UTF8);
return (Packet)xs.Deserialize(memoryStream);
}
catch (Exception e)
{
throw e;
}
}
 
O

Ollie

Hi,

I believe it would be better to convert your string into a base64 encoded
string than a UTF-8 string. Are you sure that you aren't getting some
character translation when your 'packet' class is passed over the wire?

check out base 64 encoding...

Also you can remove the number of lines from serialisation code -where
'Test' represents your class:

string ser1 = string.Empty;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
using(StringWriter sw = new StringWriter(sb))
{
XmlSerializer ser = new XmlSerializer(typeof(Test));
ser.Serialize(sw, test);

ser1 = sb.ToString();
}

And for deserialisation you can do the following - where 'Test' represents
your class:

Test test1 = null;
using(StringReader sr = new StringReader(ser1))
{
XmlSerializer ser = new XmlSerializer(typeof(Test));
test1 = (Test)ser.Deserialize(sr);
}


Hope this helps

Ollie


Newbro said:
I'm developing a server client programs which handle communications between
PC and PDA devices. XmlSerializer is used to serialize Packet object and
send/receive over networkstream.

The program works just fine initially, but choke when there's a constant
stream of data coming, which cause an XmlException to be thrown with error
"There's an error in XML document (....". For example if I were to send a
chat message Packet every other 2 seconds the program will remains ok, but
will throw an XmlException error almost instantly if I were to repeatly
sending a chat message Packet.

Basically both the server and client uses the same two functions SendPacket
and ReceivePacket to send an packet object to the other party, and a thread
calling ReceivePacket every other second.

Anyone care to enlight me on this very matter would be great. Thanks.

public void SendPacket(Packet data)
{
if (data == null) return;
try
{
String xmlString = Helper.SerializePacket(data);
Byte[] buffer = Helper.StringToUTF8ByteArray(xmlString);
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();

}
catch (Exception e)
{
throw e;
}
}

public Packet ReceivePacket()
{
try
{
Byte[] buffer = new Byte[Packet._PACKET_BYTE];
int bufferSize = networkStream.Read(buffer, 0, buffer.Length);
String xmlString = Helper.UTF8ByteArrayToString(buffer);
return (Helper.DeserializePacket(xmlString));

}
catch (Exception e)
{
throw e;
}
}

/// <summary>
/// Convert a Byte array to UTF-8 encoded string
/// </summary>
/// <param name="characters">Byte array to be converted</param>
/// <returns>String representation of given byte array</returns>
public static String UTF8ByteArrayToString(Byte[] characters)
{

UTF8Encoding encoding = new UTF8Encoding();
String constructedString = encoding.GetString(characters, 0,
characters.Length);
return (constructedString);
}

/// <summary>
/// Convert a UTF-8 encoded string to Byte array
/// </summary>
/// <param name="pXmlString">String to be converted</param>
/// <returns>Byte array representation of given string</returns>
public static Byte[] StringToUTF8ByteArray(String pXmlString)
{
UTF8Encoding encoding = new UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(pXmlString);
return byteArray;
}

/// <summary>
/// Serialize a Packet object into a UTF-8 encoded string
/// </summary>
/// <param name="packetObj">Packet to be serialized</param>
/// <returns>Serialized string of given object</returns>
public static String SerializePacket(Packet packetObj)
{
try
{
String XmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(Packet));
XmlTextWriter xmlTextWriter = new
XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, packetObj);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;
}
catch (Exception e)
{
throw e;
}
}

/// <summary>
/// Deserialize a string into Packet object
/// </summary>
/// <param name="xmlString">String to be deserialized</param>
/// <returns>Packet object of the given string</returns>
public static Packet DeserializePacket(String xmlString)
{
try
{
XmlSerializer xs = new XmlSerializer(typeof(Packet));
MemoryStream memoryStream = new
MemoryStream(StringToUTF8ByteArray(xmlString));
XmlTextWriter xmlTextWriter = new
XmlTextWriter(memoryStream, Encoding.UTF8);
return (Packet)xs.Deserialize(memoryStream);
}
catch (Exception e)
{
throw e;
}
}
 
F

Filip Larsen

Newbro skrev:
I'm developing a server client programs which handle communications between
PC and PDA devices. XmlSerializer is used to serialize Packet object and
send/receive over networkstream.

The program works just fine initially, but choke when there's a constant
stream of data coming, which cause an XmlException to be thrown with error
"There's an error in XML document (....".

I've only glanced quickly at your code, but it do seem you need to
properly demarcate the packets you send, say, using length delimiting in
your SendPacket method. Using Write to send a "bare" byte buffer will
not in itself isolate one packet from the other in the receiving end,
which may get part of one packet, or a mix of both.

Sender do like:

byte[] data = ...
Stream stream = ...
BinaryWriter out = new BinaryWriter(stream);
out.Write(data.Length);
out.Write(data);
out.Flush();

and receiver do

Stream stream = ...
BinaryReader in = new BinaryReader(stream);
int32 len = in.ReadInt32();
byte[] data = in.ReadBytes(len);



Regards,
 
N

Newbro

Yes I think that was the problem, isloating one Packet from another in
receiving.

I end up using a solution simlilar to Filip's, using first 4 bytes to hold
the length of the trailing Packet data bytes size, and seems to be working
fine just now. Thanks all


Filip Larsen said:
Newbro skrev:
I'm developing a server client programs which handle communications between
PC and PDA devices. XmlSerializer is used to serialize Packet object and
send/receive over networkstream.

The program works just fine initially, but choke when there's a constant
stream of data coming, which cause an XmlException to be thrown with error
"There's an error in XML document (....".

I've only glanced quickly at your code, but it do seem you need to
properly demarcate the packets you send, say, using length delimiting in
your SendPacket method. Using Write to send a "bare" byte buffer will
not in itself isolate one packet from the other in the receiving end,
which may get part of one packet, or a mix of both.

Sender do like:

byte[] data = ...
Stream stream = ...
BinaryWriter out = new BinaryWriter(stream);
out.Write(data.Length);
out.Write(data);
out.Flush();

and receiver do

Stream stream = ...
BinaryReader in = new BinaryReader(stream);
int32 len = in.ReadInt32();
byte[] data = in.ReadBytes(len);



Regards,
 

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