5

I'm currently testing in visual studio 2010. I made a client and server which both will connect through UdpClient.

I want to send an object from the client to the server. I have two methods to convert the object to bytes and to convert it to an object. Now, when I test my application I can't convert it back to an object once received on the server

My server sees that the object is received and tries to convert it from bytes to the object but this gives an error.

System.Runtime.Serialization.SerializationException was unhandled   Message=Unable to find assembly

This seems okay because both applications are in a different namespace...

These are my methods to convert; Both the same on client and server

public byte[] ToBytes() {
        using (MemoryStream stream = new MemoryStream()) {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);

            stream.Position = 0;

            byte[] byteRij = new byte[1024];

            stream.Read(byteRij, 0, (int)stream.Length);

            return byteRij;
        }
    }

    public static Datagram ToDatagram(byte[] rij) {
        using (MemoryStream stream = new MemoryStream()) {
            stream.Write(rij, 0, rij.Length);

            stream.Position = 0;

            BinaryFormatter formatter = new BinaryFormatter();
            return (Datagram)formatter.Deserialize(stream);
        }
    }

How can I resolve this? Thanks in advance

kendepelchin
  • 2,680
  • 2
  • 21
  • 25
  • 1
    Your `ToBytes()` method won't work correctly is the serialized form is larger than 1024 bytes. Why don't you use the [`ToArray()` method](http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx)? – svick Jun 12 '11 at 10:37

3 Answers3

3

BinaryFormatter is deeply tied to the type metadata. It is not a good choice here, since you have different types. Actually IMO it isn't a good choice anyway :) It is not very version tolerant, and is not portable.

I will openly recommend protobuf-net here (disclosure: I wrote it). It is free OSS, but uses google's protobuf format to fix all the BF problems. It is trivial to setup and use, is faster, and has smaller output than BinaryFormatter. Since it is contract-based you can have different types at each end, as log as they agree on the contract (matching field-numbers etc).

For example:

[ProtoContract]
public class Foo {
    [ProtoMember(1)]
    public string X {get;set;}
    [ProtoMember(2)]
    public int Y {get;set;}
}

And then just use ProtoBuf.Serializer.Serialize(stream, object) to write the data.

You can also work without attribute if you need, it takes a little more setup, but not much.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
3

You need to put all classes that are serialized in a class library project. Use that library in both the server and the client.

Also note that UDP is not reliable. There is no guarantee that your messages arrive at all.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • Note that this is only a BinaryFormatter requirement. You don't need this for most other serializers. – Marc Gravell Jun 12 '11 at 11:28
  • Yes, I thought I would have to make a class library. That makes sense. Also, I'm using UDP just to learn what alternatives I have. Thanks! – kendepelchin Jun 14 '11 at 11:29
2

You may be experiencing problems with unsatisfied dependency. This may be caused by different namespaces or by trying to serialize external component, which isn't installed on server.

Say: you send object of type MyApp1.MyFoo.
Class MyFoo is also defined in your server, but as MyApp2.MyFoo (which is quite silly and means that you have to fix your design). Server doesn't know how to create an object of MyApp1.MyFoo because it isn't smart enough to find out that he also has this class defined, but named MyApp2.MyFoo.

You should use same namespaces. This is what they're for. Also, they make handling dependencies easier. And MyApp.Server talking to MyApp.Client looks nice ;).

I hope you get the point.

Dr McKay
  • 2,548
  • 2
  • 21
  • 26