Avatar billede mikkelbm Nybegynder
12. juni 2005 - 17:27 Der er 11 kommentarer og
1 løsning

Problemer med Sockets

Hej

Jeg har prøvet at lave en lille client/server løsning, hvor jeg sender et objekt igennem en socket.

Nu kommer jeg fra Java verdenen, så derfor har jeg prøvet at lave det som jeg vil lave det i Java.

Mit problem er, at min server fint nok læser første client der connecter, men jeg får en exception når næste client logger på.
Den fejl jeg får er:

An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll

Additional information: Forsøger at deserialisere en tom stream.

Og bliver smidt i denne metode:

public static object ByteArray2Object(byte[] theByteArray)
{
    MemoryStream ms = new MemoryStream(theByteArray);
    try
    {
          BinaryFormatter bf = new BinaryFormatter();
          ms.Position = 0;
              return bf.Deserialize(ms); // <--- HER
    }
    finally
    {
        ms.Close();
    }
}

Som sagt kommer fejlen først, når 2. client logger på.
Avatar billede mikkelbm Nybegynder
12. juni 2005 - 17:28 #1
Server:

using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;

using BluetoneRemotingObjects;

namespace BluetoneServer
{
    class Server
    {
        [STAThread]
        static void Main(string[] args)
        {
            TcpListener listener = new TcpListener(IPAddress.Parse ("127.0.0.1"), 2048);
            listener.Start ();
            Console.WriteLine ("Server started...");
           
            while (true)
            {
                Socket socket = listener.AcceptSocket ();
                Client client = new Client (socket);
                Console.WriteLine ("Client connected...");
                Thread t = new Thread (new ThreadStart (client.Run));
                t.Start ();
            }
        }

        private class Client
        {
            private Socket socket;

            public Client (Socket socket)
            {
                this.socket = socket;
            }

            public void Run ()
            {
                byte[] buffer = new byte[socket.Available];
                int length = socket.Receive (buffer);

                UserInformation o = (UserInformation)HelperFormat.ByteArray2Object (buffer);
                Console.WriteLine (o.UserName);
                socket.Close();
            }
        }
    }
}
Avatar billede mikkelbm Nybegynder
12. juni 2005 - 17:28 #2
Client:

using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.Net.Sockets;
using System.IO;

using BluetoneRemotingObjects;

namespace TestClient
{
    class Client
    {
        [STAThread]
        static void Main(string[] args)
        {
            System.Net.Sockets.TcpClient client = new TcpClient("localhost", 2048);
            // get the NetworkStream and wrap it in a BinaryWriter
            BinaryWriter writer = new BinaryWriter(client.GetStream());
           
            UserInformation info = new UserInformation ("Mikkel", "abcdefgh");
            byte[] buffer = HelperFormat.Object2ByteArray (info);
            Console.WriteLine ("Buffer length: " + buffer.Length);

            writer.Write (buffer);
            writer.Flush ();
            writer.Close ();
            client.Close ();

            Console.WriteLine ("Object send...");
            Console.ReadLine ();
        }
    }
}
Avatar billede mikkelbm Nybegynder
12. juni 2005 - 17:28 #3
Hjælpemetoder som jeg har fundet her på Eksperten:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace BluetoneRemotingObjects
{
    public class HelperFormat
    {
        public static byte[] Object2ByteArray(Object o)
        {
            MemoryStream ms = new MemoryStream();
            try
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, o);
                return ms.ToArray();
            }
            finally
            {
                ms.Close();
            }
        }

        public static object ByteArray2Object(byte[] theByteArray)
        {
            MemoryStream ms = new MemoryStream(theByteArray);
            try
            {
                BinaryFormatter bf = new BinaryFormatter();
                ms.Position = 0;
                return bf.Deserialize(ms);
            }
            finally
            {
                ms.Close();
            }
        }
    }
}
Avatar billede arne_v Ekspert
12. juni 2005 - 17:45 #4
svært at sige

et potentielt problem er at

int length = socket.Receive (buffer);

ikke nødvendigvis vil læse hele objektet inden det returnerer nogle data
Avatar billede mikkelbm Nybegynder
12. juni 2005 - 17:46 #5
Hmmm... Okay.

Er der en bedre måde at læse data på?
Avatar billede arne_v Ekspert
12. juni 2005 - 17:46 #6
så undrer det mig at du accepter en socket og ikke en tcp client

og hvis du brugte remoting (svarende til RMI) så var du fri for alle
de manuelle serialisering og deserialisering
Avatar billede arne_v Ekspert
12. juni 2005 - 17:47 #7
start at sende 1,2 eller 4 byte med længden i client

og put Receive i en loop på server indtil du ved at du har alle bytes
Avatar billede mikkelbm Nybegynder
12. juni 2005 - 17:51 #8
Nåh ja... Det kunne jeg jo.

Jeg har fravalgt remoting, da det kun drejer sig om den smule information der er i mit wrapperobjekt: UserInformation.  Og fordi jeg ikke før har arbejdet med remoting.

Måske du kan komme med et lille hurtigt eksempel på remoting der gør det samme som ovenstående? Da det er det eneste jeg har brug for.
Avatar billede arne_v Ekspert
12. juni 2005 - 17:54 #9
alternativt kunne du også bare lade client close connection og så lade
server loop læse til EOF
Avatar billede arne_v Ekspert
12. juni 2005 - 17:54 #10
remoting er lige ud af landevejen: http://www.eksperten.dk/artikler/86
Avatar billede mikkelbm Nybegynder
12. juni 2005 - 18:00 #11
Jeg kigger lidt på det...

Smid et svar.
Avatar billede arne_v Ekspert
12. juni 2005 - 18:04 #12
ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester