2

Hey guys I'm making a chat program and I have a parent "MessagePacket" class with a bunch of child classes for different types of packets to be sent, either containing a message for the main chat window, list of people currently chatting, private chat message, etc.

In the client the first thing I do is create a "AddClientPacket" and serialize/send it to the server, the server then deserializes it as its parent "MessagePacket" class which contains a type property that is used to determine what to cast/do with the generic MessagePacket it got.

When the server trys to deserialize it it causes a crash, im not sure why. Heres some code:

--SERVER--

    private void HandleClientComm(Object client)
    {
        Client addClient = new Client(clientIds++, ((TcpClient)client).GetStream());

        IFormatter formatter = new BinaryFormatter();


        while (true)
        {
            MessagePacket packet = new MessagePacket();

            try
            {
                packet = (MessagePacket)formatter.Deserialize(addClient.ClientStream);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }



            switch (packet.Type)
            {
                case MessageType.ALLCHAT:
                    {
                        messages.Enqueue(((AllChatPacket)packet).Message);
                    }
                break;
                case MessageType.ADDCLIENT:
                    {

                        addClient.ClientName = ((AddClientPacket)packet).ClientName;
                        clientNames.Add(addClient.ClientName);
                        clientList.Add(addClient);
                    }
                break;
                case MessageType.REMOVECLIENT:
                   {
                       clientNames.Remove(addClient.ClientName);
                       clientList.Remove(addClient);
                   }
                   break;
                case MessageType.PRIVATECHAT:
                   {

                   }
                   break;
            }
        }
    }

--CLIENT--

    public void ListenToServer()
    {
        AddClientPacket addClient = new AddClientPacket();
        addClient.Type = MessageType.ADDCLIENT;


        name = addClient.ClientName = Interaction.InputBox("Whats your name", "Name?", "", 100, 100);

        try
        {
            formatter.Serialize(clientStream, addClient);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
            this.Close();
            return;
        }


        while (true)
        {
            if (quit)
            {
                break;
            }

            MessagePacket packet = new MessagePacket();

            try
            {
                packet = (MessagePacket)formatter.Deserialize(clientStream);
            }
            catch (Exception)
            {
                return;
            }

            switch (packet.Type)
            {
                case MessageType.ALLCHAT:
                    {
                        textBox1.Text = textBox1.Text + Environment.NewLine + ((AllChatPacket)packet).Message;
                        textBox1.Refresh();
                    }
                    break;
                case MessageType.NAMELIST:
                    {
                        clientNameList.DataSource = ((NameListPacket)packet).ClientNames;
                    }
                    break;
            }
        }
    }
4
  • No exceptions are thrown? Anything in the event log about the crash? You can try putting AppDomain.Current.UnhandledExceptions += (a,b) => File.WriteAllText("errorlog.txt", b.ExceptionObject) to catch the last error that was thrown. You can try creating a hash of the raw bytes of the packet you are serializing, then on the server read the TcpClient stream directly, then hash that to make sure the hashes are the same. This will ensure that the data is being transported correctly. Commented Oct 7, 2012 at 23:12
  • Yes sorry an exception is thrown and the message is: "Unable to find assembly 'ChatClient, Version1.0.0.0, Culture=neutral, PublicKeyToken=null' Although the ChatServer is the one throwing it after trying to Deserualize message from ChatClient Commented Oct 9, 2012 at 1:48
  • 1
    Right, so is the ChatClient.dll in the same directory as the ChatServer .exe? If you have a custom Packet type that both Client and Server need to use, usually you will abstract this into it's own assembly (.dll) so that it can be shared by both. Commented Oct 9, 2012 at 1:53
  • I gotcha. Right now there completely separate projects, and both contain the classes for the MessagePackets. That is definitely something I should look into doing, so I don't have to duplicate the code. But right now both projects do contain the same class definitions so I can't see that being the issue. Commented Oct 9, 2012 at 2:19

1 Answer 1

1

That would be the issue then. Even though they 'look' the same to you, have the same properties, .NET sees them as completely different types if they are defined in two different assemblies and therefore will not let you serialize TypeA and deserialize it into TypeB. You are going to have to create a single .dll with that class definition that both share.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.