473,385 Members | 1,620 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

xmlserializer and sockets

hi, i have some problems with my client talk to my server...
i am using xmlserializer to serialize object and send them to the other
side of the connection. I need to send / recive by both client and
server. client after login waits all the time listening for objects on a
thread, and sends objects on users events on the main thread. server
waits connections, start a new thread for each connection and after
validating login waits for object, and answer with an object to every
incoming object.

If i send only one packet, all works fine, i tryed many solution but i
cannot send 2 packets, or send and recive...

here is my code:

LoginPacket is a class with informations

SERVER SIDE:
the method run of this class is launched as a thread to serve a client,
with a socket initializated (and passed as parameter)
now for testing it will only waits for 2 login packets

public class ServeClient {
private Socket sock;
public ServeClient(Socket s) {
this.sock = s;
}
public void Run(){
NetworkStream networkStream = new NetworkStream(sock);

//waiting for login request
LoginPacket lp;
this.DeserializeMessage( networkStream, out lp);

LoginPacket lp2;
this.DeserializeMessage( networkStream, out lp2);
Console.WriteLine("Incoming login request: {0}", lp.Nick);

networkStream.Close();
sock.Close();
}
// this will deserialize the message, and put it in message
public bool DeserializeMessage(NetworkStream networkStream,out
LoginPacket message) {
Byte []buffer=new Byte[500];
XmlSerializer deserializer=new XmlSerializer(typeof(LoginPacket));
int count=networkStream.Read(buffer,0,buffer.Length);
if(count <= 0) {
message=null;
return false;
}
MemoryStream memoryStream=new MemoryStream(buffer,0,count);
message= ((LoginPacket)deserializer.Deserialize(memoryStrea m));
return true;
}
}

CLIENT SIDE:
// run is launched as a thread, this thread will wait listening after
// login succed. now for testing it will only send 2 login requests
class ListenerThread {
private TcpClient client; //FIXME : it is no syncronized
public void Run() {
client = new TcpClient( "localhost", 6666);;
LoginPacket login = new LoginPacket( PacketType.LOGIN_REQUEST,
"nick", "pass");

LoginPacket login2 = new LoginPacket( PacketType.LOGIN_REQUEST,
"nick2", "pass2");
this.Send(login);
this.Send(login2);

client.Close();

}
//send a loginpacket
public void Send(LoginPacket message) {
NetworkStream netWorkStream=null;
XmlSerializer serializer=new XmlSerializer(message.GetType());
//Fixme: metterlo fuori dal metodo
netWorkStream = client.GetStream();
Stream stream=(Stream)netWorkStream;
serializer.Serialize(stream,message);
}
}

thx if someone can solve my problems.
Nov 16 '05 #1
4 5385
What is the error message you get?

Anyway, there are some invalid assumptions in your code. See below:

"Ultrakorne" <ul********@freeweb.org> wrote in message
news:1S**********************@news4.tin.it...
hi, i have some problems with my client talk to my server...
i am using xmlserializer to serialize object and send them to the other
side of the connection. I need to send / recive by both client and server.
client after login waits all the time listening for objects on a thread,
and sends objects on users events on the main thread. server waits
connections, start a new thread for each connection and after validating
login waits for object, and answer with an object to every incoming
object.

If i send only one packet, all works fine, i tryed many solution but i
cannot send 2 packets, or send and recive...

here is my code:

LoginPacket is a class with informations

SERVER SIDE:
the method run of this class is launched as a thread to serve a client,
with a socket initializated (and passed as parameter)
now for testing it will only waits for 2 login packets

public class ServeClient {
private Socket sock;
public ServeClient(Socket s) {
this.sock = s;
}
public void Run(){
NetworkStream networkStream = new NetworkStream(sock);

//waiting for login request
LoginPacket lp;
this.DeserializeMessage( networkStream, out lp);

LoginPacket lp2;
this.DeserializeMessage( networkStream, out lp2);
Console.WriteLine("Incoming login request: {0}", lp.Nick);

networkStream.Close();
sock.Close();
}
// this will deserialize the message, and put it in message
public bool DeserializeMessage(NetworkStream networkStream,out
LoginPacket message) {
Byte []buffer=new Byte[500];
XmlSerializer deserializer=new XmlSerializer(typeof(LoginPacket));
int count=networkStream.Read(buffer,0,buffer.Length);
if(count <= 0) {
message=null;
return false;
}


You assume that 'buffer' now contains the serialized data for one
LoginPacket, but this is not necessarily the case. It could contain data for
half of a LoginPacket, one and a half, two LoginPackets, or anything in
between. The basic issue here is that TCP is a stream-oriented protocol and
the stuff you send arrives to its destination as an unstructured stream of
bytes.

One way to solve the problem would be to first send the size of the
serialized LoginPacket (number of bytes) and then the LoginPacket itself.
The receiver would first read the size and then the expected number of bytes
into the buffer. The receiver should deserialize the LoginPacket only after
the expected number of bytes have arrived and are in the buffer.

Another way that might work (don't have the time to try it now) would be to
have the XmlSerializer deserialize straight from the NetworkStream.

Regards,
Sami

Nov 16 '05 #2
> Another way that might work (don't have the time to try it now) would be
to
have the XmlSerializer deserialize straight from the NetworkStream.


I was thinking that too. However it probably exposes server to DoS attacks.
If you know the len before hand, you can decide if want to read that many
bytes or not. So the safe way is to send the len (i.e. uint) before hand
and read that many bytes, then deserialize that byte[]. Maybe something
like:

// Object
XmlRequest xr = new XmlRequest();
xr.Data = "Hello";

// Serialize it.
MemoryStream ms = new MemoryStream();
ms.Position = 4; // leave 4 bytes for our len.
XmlSerializer ser = new XmlSerializer(typeof(XmlRequest));
ser.Serialize(ms, xr);
int size = (int)ms.Length - 4;
byte[] lenBytes = BitConverter.GetBytes(size);
ms.Position = 0;
ms.Write(lenBytes, 0, 4);

// Write ms bytes to socket.

// Deserialize it.
ms.Position = 0; // pretent we blocking on first byte.
ms.Read(lenBytes, 0, 4); // pretent we read four bytes.
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = new byte[len];
ms.Read(bytes, 0, len); // read len count data bytes only.
string xmlString = Encoding.UTF8.GetString(bytes, 0, bytes.Length); //
Used by Stream overload on xmlserializer.
Console.WriteLine("Raw:"+xmlString);
XmlSerializer ser2 = new XmlSerializer(typeof(XmlRequest));
using (StringReader sr = new StringReader(xmlString))
{
xr = (XmlRequest)ser.Deserialize(sr);
Console.WriteLine("Data:"+xr.Data);
}

--
William Stacey, MVP
http://mvp.support.microsoft.com
Nov 16 '05 #3
Sami Vaaraniemi wrote:
What is the error message you get?

Anyway, there are some invalid assumptions in your code. See below:

i have changed the recive method and make it simpler:

public LoginPacket DeserializeMessage() {
NetworkStream networkStream = new NetworkStream(sock);
LoginPacket message = null;
try {
message = ((LoginPacket)deserializer.Deserialize(networkStre am));
} catch(Exception e) { Console.WriteLine("EXC 3"); return null; }
finally {
networkStream.Close();
}
return message;
}

deserializer is XmlSerializer = new XmlSerializer(typeof(LoginPacket));

the problem is the same: exception is raised by .Deserialize:
System.Xml.XmlException: XML declaration cannot appear in this state.
Line 5, position 20.

William Stancey wrote:
I was thinking that too. However it probably exposes server to DoS
attacks.
If you know the len before hand, you can decide if want to read that
many
bytes or not. So the safe way is to send the len (i.e. uint) before
hand
and read that many bytes, then deserialize that byte[]. Maybe
something like:


thanks for your hit, but first i have to solve and understand whats
wrong with my code
Nov 16 '05 #4
I did a bit of digging and here's what I found out.

It seems that XmlSerializer.Deserialize blocks until it gets end-of-file or
its internal buffer of 4k is full. If the sender closes the socket after the
LoginPacket is sent, then it works and the deserialized object is returned
properly. But this is hardly a solution as you want to send more than just
the one LoginPacket. On the other hand, if there is more data coming from
the socket after the last closing tag, then XML parsing fails and there is
an exception.

Bottom line, it appears you cannot call XmlSerializer.Deserialize with a
NetworkStream, or at least I could not figure out how to make it work. Even
if it were possible, you probably don't want to do it this way as the server
would be vulnerable to a DoS attack just like William pointed out.

So the solution is to first send the length of the serialized object, and
then the serialized object itself. The receiver should copy the bytes from
the socket into a temporary buffer, then deserialize out of the buffer.

Alternatively, you could use the BinaryFormatter instead of XmlSerializer as
it does not suffer from the blocking problem.

Regards,
Sami

"ultrakorne" <ul********@paranoici.org> wrote in message
news:41**************@paranoici.org...
Sami Vaaraniemi wrote:
What is the error message you get?

Anyway, there are some invalid assumptions in your code. See below:


i have changed the recive method and make it simpler:

public LoginPacket DeserializeMessage() {
NetworkStream networkStream = new NetworkStream(sock);
LoginPacket message = null;
try {
message = ((LoginPacket)deserializer.Deserialize(networkStre am));
} catch(Exception e) { Console.WriteLine("EXC 3"); return null; }
finally {
networkStream.Close();
}
return message;
}

deserializer is XmlSerializer = new XmlSerializer(typeof(LoginPacket));

the problem is the same: exception is raised by .Deserialize:
System.Xml.XmlException: XML declaration cannot appear in this state. Line
5, position 20.

William Stancey wrote:
I was thinking that too. However it probably exposes server to DoS
attacks.
If you know the len before hand, you can decide if want to read that
many
bytes or not. So the safe way is to send the len (i.e. uint) before
hand
and read that many bytes, then deserialize that byte[]. Maybe
something like:


thanks for your hit, but first i have to solve and understand whats wrong
with my code

Nov 16 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Stuart Robertson | last post by:
I am trying to find a solution that will allow me to use XmlSerializer to serialize/deserialize a collection of objects where a given object is shared between two or more other objects, and not...
1
by: Bluetears76 | last post by:
Hi I have a hirachy of classes which are Message(base), then FileMessage and ChatMessage (extended) I want to serialize the objects and when i am deserizaling i dont know if i am getting...
3
by: Anthony Bouch | last post by:
Hi I've been reading using the XmlSerializer with custom collections. I've discovered that when serializing a custom collection (a class that implements ICollection, IList etc.) the...
3
by: Loui Mercieca | last post by:
Hi, I have created a class, named FormField , which basically contains two fields, name and value. I have set the tag before the class and the field is set as an XmlAttribute whil the name as...
12
by: SJD | last post by:
I've just read Christoph Schittko's article on XmlSerializer: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnxmlnet/html/trblshtxsd.asp . . . and very informative it is too....
4
by: Steve Long | last post by:
Hello, I hope this is the right group to post this to. I'm trying to serialize a class I've written and I'd like to be able to serialze to both binary and xml formats. Binary serialization is...
7
by: Bill English | last post by:
How do I send an object from one computer to another? -- I am a 14 year old C# developer, I am completely self taught, so please don't get mad if I ask a stupid question. Thanks.
2
by: Curious | last post by:
Hi, I have a similar class to the one shown below, with the main difference that it has more properties. Now I am using the enum to indicate what type of data current exists. I am using...
3
by: Curious | last post by:
Hi, I am using the following code to transfer messages between client and server. Upon running that code I am getting the following error message in method ReceiveFromClient on line Stream s...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.