двоичный форматтер десериализует из замораживания потока памяти - PullRequest
1 голос
/ 09 мая 2020

Я пытаюсь создать клиент-серверное приложение, которое обменивается данными через сокеты, и их сообщения последовательны и десериализованы с использованием BinaryFormatter. Мой код зависает и абсолютно ничего не делает при достижении десериализации, и я не понимаю почему, поскольку у меня нет исключений. Я тоже не могу зайти с отладчиком, все зависает. Это мой код:

 public class Serializer
    {
        public static MemoryStream ToStream(object obj)
        {
            var stream = new MemoryStream();
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, obj);
            return stream;
        }

        public static object FromStream(MemoryStream stream)
        {
            Console.WriteLine("Starting from stream");
            var formatter = new BinaryFormatter();
            stream.Seek(0, SeekOrigin.Begin);
            object rez = formatter.Deserialize(stream); //NEVER GOES OVER THIS
            Console.WriteLine("Starting deserialization" + rez);
            return formatter.Deserialize(stream);
        }
    }
public class Connection
    {
        private Socket socket;
        public Connection(Socket socket)
        {
            this.socket = socket;
            Console.WriteLine($"Connected to client: {socket.RemoteEndPoint}");
            Task.Factory.StartNew(() => Execute(socket));
        }

        private void Execute(Socket socket)
        {
            while (true)
            {
                var buffer = new byte[2048];
                var bytesCount = socket.Receive(buffer);
                if(bytesCount != 0)
                {
                    var msgReceived = (Message)Serializer.FromStream(new MemoryStream(buffer, 0, buffer.Length));
                    Console.WriteLine($"Received msg: {msgReceived.Content}");
                }
               /* var msg = new Message { Content = "Hello World2!" };
                Console.WriteLine($"Sending msg with content: {msg.Content}");
                MemoryStream stream = Serializer.ToStream(msg);
                var bytesSent = socket.Send(stream.GetBuffer());*/

                Console.WriteLine("Trying again");
                Thread.Sleep(500);
            }
        }

код клиента:

  var host = Dns.GetHostEntry("localhost");
            var ipAddress = host.AddressList.First();
            var serverEndpoint = new IPEndPoint(ipAddress, 9000);

            Socket serverSocket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Connect(serverEndpoint);

            Console.WriteLine($"Successfully connected to server on: {serverSocket.RemoteEndPoint}");

            while (true)
            {
                var msg = new Message { Content = "Hello World!" };
                Console.WriteLine($"Sending msg with content: {msg.Content}");
                MemoryStream stream = Serializer.ToStream(msg);
                var bytesSent = serverSocket.Send(stream.GetBuffer());
                Console.WriteLine("Waiting to receive");

                var buffer = new byte[2048];
                int bytesReceived = serverSocket.Receive(buffer);
                if (bytesReceived != 0)
                {
                    var receivedMessage = (Message)Serializer.FromStream(new MemoryStream(buffer));
                    Console.WriteLine($"Received message: {receivedMessage.Content}");
                }

                Console.WriteLine("Received done");

            }

код сервера:

var host = Dns.GetHostEntry("localhost");
            var ipAddress = host.AddressList.First();
            var localEndPoint = new IPEndPoint(ipAddress, 9000);
            var serverSocket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(localEndPoint);
            serverSocket.Listen(1);

            while (true)
            {
                Console.WriteLine("Waiting for client");
                Socket clientSocket = serverSocket.Accept();
                var connection = new Connection(clientSocket);
            }

Я также проверил byteCount, и они прибывают к серверу, также буфер не пуст, я не понимаю, почему десериализация ничего не делает ..

Ответы [ 2 ]

0 голосов
/ 09 мая 2020

Вы дважды вызываете Deserialize, я думаю, проблема здесь:

object rez = formatter.Deserialize(stream); //NEVER GOES OVER THIS
Console.WriteLine("Starting deserialization" + rez);
return formatter.Deserialize(stream);

Я думаю, вы можете использовать такие методы:

    private byte[] SerializeMessage(Message msg)
    {
        var formatter = new BinaryFormatter();
        byte[] buf;
        using (MemoryStream stream = new MemoryStream())
        {
            formatter.Serialize(stream, msg);
            buf = new byte[stream.Length];
            return stream.ToArray();
        }
    }

     private Message DeserializeMessage(byte[] buff)
     {
            var formatter = new BinaryFormatter();
            ConnectingMessage msg;
            using (Stream stream = new MemoryStream(buff))
            {
                msg = formatter.Deserialize(stream) as Message;
            }

            return msg;           
     }

Также методы Send / Receive синхронны, они блокируют выполнение потока.

Описание асинхронной опции здесь https://docs.microsoft.com/en-us/dotnet/framework/network-programming/using-an-asynchronous-client-socket

0 голосов
/ 09 мая 2020

Одновременно может выполняться только один фрагмент кода. Пока работает этот бесконечный l oop while (true), никакой другой код не сможет работать.

Вам нужно будет добавить в этот проект немного многозадачности. Минимальная сумма, необходимая для каждого текстового процессора. Однако вы также, похоже, программируете в консоли. По моему опыту, консоль и многозадачность не так хорошо сочетаются. Вам нужно поддерживать программу в рабочем состоянии, не блокируя ввод.

Мой совет по изучению многозадачности - это BackgroundWorker в Windows Forms. BGW устарела, используйте потоки, которые здесь не нужны и не должны использоваться в продуктивном коде. Но это, пожалуй, лучшие "обучающие колеса" для многозадачности и многопоточности, о которых я знаю.

...