← Zurück

Передача объектов по трубам

Можно ли передавать через именованные каналы объекты, а не только стринговые сообщения? Ни в одном найденном мной примере про NamedPipes не нашёл передачу чего-либо кроме текста.

War dieses Thema hilfreich?

Thema teilen

Kommentare (10)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Mikhail Sukhov
Mikhail Sukhov

Через сетевое соединение передаются только байты, не стринги и не числа. В байты можно перевести все что угодно. Это называется сериализация. Наши классы (из BisEnt) поддерживают WCF сериализацию.

Buratino
Buratino Autor

Михаил Сухов: Через сетевое соединение передаются только байты, не стринги и не числа. В байты можно перевести все что угодно. Это называется сериализация. Наши классы (из BisEnt) поддерживают WCF сериализацию.

Да-да, вот как раз пытался сериализовать и в бинарник, и в XML. Но даже не вижу на какой стороне проблема, сервера или клиента. Если есть под рукой пример, скиньте, пожалуйста.

Mikhail Sukhov
Mikhail Sukhov

Buratino:

Михаил Сухов: Через сетевое соединение передаются только байты, не стринги и не числа. В байты можно перевести все что угодно. Это называется сериализация. Наши классы (из BisEnt) поддерживают WCF сериализацию.

Да-да, вот как раз пытался сериализовать и в бинарник, и в XML. Но даже не вижу на какой стороне проблема, сервера или клиента. Если есть под рукой пример, скиньте, пожалуйста.

Под рукой простого примера нет. А в чем выражается проблема? Попробуйте вначале делать сериализацию-десериализацию локально, без пайпов. Чтобы проверить, что она правильно происходит. А потом уже пайпы. Сложное - это всегда передача состояния. Сам трансфер данных - прост до безобразия. Пайпы - это не сокеты. Тут ни датаграм, ни пакетов. Все передается как есть.

Buratino
Buratino Autor

Михаил Сухов:

Buratino:

Михаил Сухов: Через сетевое соединение передаются только байты, не стринги и не числа. В байты можно перевести все что угодно. Это называется сериализация. Наши классы (из BisEnt) поддерживают WCF сериализацию.

Да-да, вот как раз пытался сериализовать и в бинарник, и в XML. Но даже не вижу на какой стороне проблема, сервера или клиента. Если есть под рукой пример, скиньте, пожалуйста.

Под рукой простого примера нет. А в чем выражается проблема? Попробуйте вначале делать сериализацию-десериализацию локально, без пайпов. Чтобы проверить, что она правильно происходит. А потом уже пайпы. Сложное - это всегда передача состояния. Сам трансфер данных - прост до безобразия. Пайпы - это не сокеты. Тут ни датаграм, ни пакетов. Все передается как есть.

C сериализацией уже экспериментировал, сохранял и загружал из файлов.

Переделал такой консольный пример. В методе Main закоментены вызовы первой пары методов, которые успешно передают и получают текстовые сообщение. Проблема со второй парой. Сервер не принимает заполненный словарь, формат не разберёт.


using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;

namespace PipeApplication1
{
    class ProgramPipeTest
    {

        public void ThreadStartServer()
        {
            // Create a name pipe
            using (NamedPipeServerStream pipeStream = new NamedPipeServerStream("mytestpipe2"))
            {
                Console.WriteLine("[Server] Pipe created {0}", pipeStream.GetHashCode());

                // Wait for a connection
                pipeStream.WaitForConnection();
                Console.WriteLine("[Server] Pipe connection established");

                using (StreamReader sr = new StreamReader(pipeStream))
                {
                    string temp;
                    // We read a line from the pipe and print it together with the current time
                    while ((temp = sr.ReadLine()) != null)
                    {
                        Console.WriteLine("{0}: {1}", DateTime.Now, temp);
                    }
                }
            }

            Console.WriteLine("Connection lost");
        }

        public void ThreadStartClient(object obj)
        {
            // Ensure that we only start the client after the server has created the pipe
            ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

            // Only continue after the server was created -- otherwise we just fail badly
            // SyncClientServer.WaitOne();

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream("mytestpipe2"))
            {
                // The connect function will indefinately wait for the pipe to become available
                // If that is not acceptable specify a maximum waiting time (in ms)
                pipeStream.Connect();

                Console.WriteLine("[Client] Pipe connection established");
                using (StreamWriter sw = new StreamWriter(pipeStream))
                {
                    sw.AutoFlush = true;
                    string temp;
                    Console.WriteLine("Please type a message and press [Enter], or type 'quit' to exit the program");
                    while ((temp = Console.ReadLine()) != null)
                    {
                        if (temp == "quit") break;
                        sw.WriteLine(temp);
                    }
                }
            }
        }



        public void BinServer()
        {
            BinaryFormatter binFormat = new BinaryFormatter();

            // Create a name pipe
            using (NamedPipeServerStream pipeStream = new NamedPipeServerStream("mytestpipe1"))
            {
                Console.WriteLine("[Server] Pipe created {0}", pipeStream.GetHashCode());

                // Wait for a connection
                pipeStream.WaitForConnection();
                Console.WriteLine("[Server] Pipe connection established");

                byte[] buffer = new byte[65000];
                pipeStream.Read(buffer, 0, buffer.Length);
                var stream = new MemoryStream(buffer);
                var obj = (Dictionary<int, string>)binFormat.Deserialize(stream);
                Console.WriteLine(obj);
            }
        }

        public void BinClient(object obj)
        {
            var dic = new Dictionary<int, string> {{11, "hello"}, {22, "world"}};

            BinaryFormatter binFormat = new BinaryFormatter();
            var stream = new MemoryStream();
            binFormat.Serialize(stream, dic);

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream("mytestpipe1"))
            {
              
                pipeStream.Connect();
                Console.WriteLine("[Client] Pipe connection established");

                byte[] buffer = new byte[65000];
                buffer = Encoding.UTF8.GetBytes(Convert.ToString(stream));

                pipeStream.Write(buffer,0,buffer.Length);

            }
        }

        static void Main(string[] args)
        {

            // To simplify debugging we are going to create just one process, and have two tasks
            // talk to each other. (Which is a bit like me sending an e-mail to my co-workers)

            ProgramPipeTest Server = new ProgramPipeTest();
            ProgramPipeTest Client = new ProgramPipeTest();

            //Thread ServerThread = new Thread(Server.ThreadStartServer);
            //Thread ClientThread = new Thread(Client.ThreadStartClient);
            Thread ServerThread = new Thread(Server.BinServer);
            Thread ClientThread = new Thread(Client.BinClient);

            ServerThread.Start();
            ClientThread.Start();
        }
    }
}

Mikhail Sukhov
Mikhail Sukhov

Buratino: ...

Buratino
Buratino Autor

Михаил Сухов:

Buratino: ...

А как это тогда стандартизировать под один объём?

Посылаю текстовые сообщения из одного приложения в другое - нормально. Стоит заменить на структуру или класс и всё, то нарушен канал, то не удаётся десереализировать.

Mikhail Sukhov
Mikhail Sukhov

Buratino: А как это тогда стандартизировать под один объём?

Никак. Разные данные имеют разные длины. Нужно посылать вначале ввиде 2-3-ех байт размер сообщения, а дальше уже само сообщение. Чтобы принимающая сторона знала, сколько ей считывать.

Buratino
Buratino Autor

Михаил Сухов:

Buratino: А как это тогда стандартизировать под один объём?

Никак. Разные данные имеют разные длины. Нужно посылать вначале ввиде 2-3-ех байт размер сообщения, а дальше уже само сообщение. Чтобы принимающая сторона знала, сколько ей считывать.

По идее такая конструкция должна считывать всё посланное сообщение целиком.


                        byte[] buffer = new byte[1024];
                        while(pipeServer.Read(buffer, 0, buffer.Length) != 0);

По крайней мере у меня заполненным оказывается весь килобайт, полезной информации которой составляет на самом деле треть. После этого он мне выкидывает экцепцию "Не удалось найти сборку". Даже с учётом того, что структуру я вынес в отдельную библиотеку, правда так до сих пор не понятно зачем это нужно, ведь она была прописана внутри класса, скопипастена с входящего конца трубы.

IvanB
IvanB

В место

Encoding.UTF8.GetBytes(Convert.ToString(stream));

лучше использовать

stream.ToArray();

И предлагаю посмотреть на решение по сеирализации\десериализации предложенное на форуме: http://stackoverflow.com/questions/4021893/saving-a-dictionarystring-int32-in-c-sharp-serialization

Buratino
Buratino
Buratino Autor

IvanB: В место

Encoding.UTF8.GetBytes(Convert.ToString(stream));

> лучше использовать
> ```csharp
stream.ToArray();

И предлагаю посмотреть на решение по сеирализации\десериализации предложенное на форуме: http://stackoverflow.com/questions/4021893/saving-a-dictionarystring-int32-in-c-sharp-serialization

В MSDN говорят, что класс BinaryWriter работает только с простыми типами данных, а такой как словарь, наверное, сложный.