Форум русскоязычного сообщества Ubuntu


Хотите сделать посильный вклад в развитие Ubuntu и русскоязычного сообщества?
Помогите нам с документацией!

Автор Тема: Вопрос по моно.  (Прочитано 1381 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Вопрос по моно.
« : 05 Октября 2009, 11:58:15 »
Имеется некоторые данные в структуре (без функций чистые данные типа bool, byte, int, double), которые находятся на сервере. По запросу клиента данные сериализируются и через сокет передаются клиенту. У клиента данные десериализируются в первоначальный вид для использования на клиенте.
Вопрос.
Сам сериализатор - десериализатор отдельно работает.
Сокет работает, но десериализация несет какую-то ахинею (см. лог).

mono AsyncClient.exe
Connecting to server: localhost
--------------------
Send to Server: Give me your Data
Receved from Server: 187 bytes

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'AsyncServer' or one of its dependencies. The system cannot find the file specified.
File name: 'AsyncServer'
  at (wrapper managed-to-native) System.AppDomain:LoadAssembly (string,System.Security.Policy.Evidence,bool)
  at System.AppDomain.Load (System.String assemblyString) [0x00000]
  at (wrapper remoting-invoke-with-check) System.AppDomain:Load (string)
  at System.Reflection.Assembly.Load (System.String assemblyString) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetDeserializationType (Int64 assemblyId, System.String className) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadTypeMetadata (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectInstance (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (System.IO.BinaryReader reader) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00000]
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) [0x00000]
  at Asutp.Data.dataFunc.DeserializeData (System.Byte[]& buf, Int32 len) [0x00000]
  at Asutp.AsyncClient.AsyncClient.Run () [0x00000]
  at Asutp.AsyncClient.AsyncClient.Main (System.String[] args) [0x00000]
al@ubuntu-desktop1:~/Desktop/ASUTP/TCP/AsyncClient/AsyncClient/bin/Debug$

Сижу и не могу ничего понять. Без сериализации-десериализации все работает. Сама сериализация-десериализация тоже. А с разнесенной сериализацией на сервере и десериализацией на клиенте полный облом.
Буду очень благодарен за наводку.

Пользователь решил продолжить мысль 05 Октября 2009, 08:09:25:
На всякий случай лог на сервере.

Client connected
Получено от клиента 18 байт
Отправлено клиенту 187 байт
Write complete
Read connection dropped

Т.е. клиент получает все сполна.


Пользователь решил продолжить мысль 05 Октября 2009, 13:41:04:
Вот нашел что-то близкое.
http://www.sql.ru/forum/actualthread.aspx?tid=128517
Попробую, но умом это не понимаю.

Пользователь решил продолжить мысль 05 Октября 2009, 17:42:07:
Попробовал сериализацию-десериализацию разбитую по разным приложениям. Результат  как с сокетом, аналогичный. Те же сообщения. Ситуация проясняется.
« Последнее редактирование: 05 Октября 2009, 17:42:07 от alexander.pronin »

Оффлайн xRay

  • Новичок
  • *
  • Сообщений: 10
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #1 : 05 Октября 2009, 19:51:25 »
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'AsyncServer' or one of its dependencies. The system cannot find the file specified.
File name: 'AsyncServer'
...
al@ubuntu-desktop1:~/Desktop/ASUTP/TCP/AsyncClient/AsyncClient/bin/Debug$

Судя по ошибке нет сборки AsyncServer.
They who can give up essential liberty to obtain a little temporary safety, deserve neither liberty nor safety © Benjamin Franklin

Оффлайн axe

  • Старожил
  • *
  • Сообщений: 1203
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #2 : 06 Октября 2009, 00:45:07 »
Сложно гадать, не видя кода, но по-моему, ситуация следующая: вы отдельно, на клиенте и на сервере, определили 2 различных структуры (читай - 2 различных типа) с одинаковой структурой. Беда в том, что при бинарной сериализации в поток данных записываются не только собственно данные, но и информация о типе. Т.е. чтобы десериализовать на клиенте то, что было сериализовано на сервере, клиенту нужен ровно тот же тип, что на сервере (а не просто совпадающий по формату).

Если я угадал, то возможны 2 решения:
1) Правильное: вынести такие общие типы в отдельную сборку, которую reference'ят и клиент и сервер.
2) Использовать не бинарную, а Xml сериализацию - там как раз нужно только совпадение структуры (ну и соответствующие атрибуты). Но это не лучшее решение, я советую первый вариант.

А вообще, в .NET есть очень хороший механизм клиент-серверного взаимодействия - Remoting. Правда, как с поддержкой Remoting обстоят дела в Mono, совершенно не в курсе.

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #3 : 06 Октября 2009, 11:30:41 »
Сложно гадать, не видя кода, но по-моему, ситуация следующая: вы отдельно, на клиенте и на сервере, определили 2 различных структуры (читай - 2 различных типа) с одинаковой структурой. Беда в том, что при бинарной сериализации в поток данных записываются не только собственно данные, но и информация о типе. Т.е. чтобы десериализовать на клиенте то, что было сериализовано на сервере, клиенту нужен ровно тот же тип, что на сервере (а не просто совпадающий по формату).
Структура данных (сериализуемая) и класс сериализации-десериализации лежит в отдельном файле (он имеет 1 экземпляр данных) и в одном пространстве имен. Я его подключаю как внешний файл в проект сервера и проект клиента. В клиенте и в сервере идет работа только с функциями класса сериализации-десериализации.

Если я угадал
Все верно.

1) Правильное: вынести такие общие типы в отдельную сборку, которую reference'ят и клиент и сервер.
Вы имеете ввиду сделать DLL, на сериализуемые данные или на сериализуемые данные и класс сериализации - десериализации. Или сделать сериализуемые данные и класс сериализации - десериализации одним классом и сделать DLL.
Здесь пока я и плаваю.

2) Использовать не бинарную, а Xml сериализацию - там как раз нужно только совпадение структуры (ну и соответствующие атрибуты). Но это не лучшее решение, я советую первый вариант.
Этот вариант как-то совсем не в жилу.

А вообще, в .NET есть очень хороший механизм клиент-серверного взаимодействия - Remoting. Правда, как с поддержкой Remoting обстоят дела в Mono, совершенно не в курсе.
Что-нибудь по этому вопросу посмотреть было бы здорово.

Пользователь решил продолжить мысль 06 Октября 2009, 11:44:17:
Посмотрел remoting
http://ru.wikipedia.org/wiki/.Net_Remoting
COM, DCOM - это прошлое.
А WCF поддерживается в нет 3.0.
В моно поддерживает нет 2.0 в полном объеме, а 3.0 пока неизвестно когда.
Остается вариант 1.
« Последнее редактирование: 06 Октября 2009, 11:44:17 от alexander.pronin »

Оффлайн axe

  • Старожил
  • *
  • Сообщений: 1203
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #4 : 06 Октября 2009, 12:30:19 »
Цитировать
1) Правильное: вынести такие общие типы в отдельную сборку, которую reference'ят и клиент и сервер.
Вы имеете ввиду сделать DLL, на сериализуемые данные или на сериализуемые данные и класс сериализации - десериализации. Или сделать сериализуемые данные и класс сериализации - десериализации одним классом и сделать DLL.
Сделать DLL, в которой будет находиться сериализуемые/десериализуемые типы, и подключать ее как reference для клиента и сервера (а не как исходный файл).

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #5 : 06 Октября 2009, 13:34:48 »
Вот модуль с сериализуемыми данными и классом функций работы с ним.
Я использую асинхронную передачу данных, поэтому работаю через буфер, параметры которого передаются как параметры функций. Что делать dll пока неясно.

using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;
//using Asutp.Data;

namespace Asutp.Data
{
   
//----------------------------------------------------   
// Это данные, собираемые на сервере концентраторе
// передаваемые клиенту как сериализованная структура
   [Serializable]
//   class Data : Component {
   class Data  {

      public bool Alarm_1;
      public bool Alarm_2;
      public bool NoLinkModBus;
      public bool Signal_4;
      public int Int_1;
      public int Int_2;
      public byte Byte_1;
      public double I1;
      public double U1;
      public double P1;
   }
   
//   class dataFunc : Component{
   class dataFunc {
      Data data=new Data();
      
      public void PrintData()
      {
         Console.WriteLine(@"Data of Server:
Alarm_1= {0}            Alarm_2={1}
NoLinkModBus={2}        Signal_4={3}
Int_1={4}               Int_2={5}
Byte_1={6}
I1={7}
U1={8}
P1={9}
",data.Alarm_1,data.Alarm_2,data.NoLinkModBus,data.Signal_4,data.Int_1,
data.Int_2,data.Byte_1,data.I1,data.U1,data.P1
);
         
         
      }
      public void WriteData()
      {
         data.Alarm_1=false;
         data.Alarm_2=true;
         data.Byte_1=200;
         data.Int_1=123;
         data.Int_2=234;
         data.NoLinkModBus=false;
         data.Signal_4=true;
         data.I1=1.1;
         data.U1=2.2;
         data.P1=3.3;
      }
      // сериализация данных для передачи по каналам связи
      // выполняется на сервере
      public void SerializeData(ref byte[] buf, ref int len)
      {
         // создаем поток для записи
         MemoryStream memS = new MemoryStream();
         memS.Capacity = 1024;
         // помещаем данные в поток в двоичном формате
         BinaryFormatter bf = new BinaryFormatter();
         memS.Position=0;
         bf.Serialize(memS, data);
         //memS.Seek(0, SeekOrigin.Begin);
         memS.Position=0;
         memS.Read(buf,0,(int)memS.Length); // читаем из виртульного файла в буфер
         len=(int)memS.Length;
         memS.Close();
         Console.WriteLine("Отправлено клиенту {0} байт",len);

      }
      // десериализация данных после приема по каналам связи
      // выполняется на клиенте
      public void DeserializeData(ref byte[] buf, int len )
      {
         // создаем поток для чтения
         MemoryStream memS = new MemoryStream();
         memS.Capacity = 1024;
         memS.Position=0;
         memS.Write(buf,0,len);// пишем буфер в виртуальный файл
         
         //memS.Seek(0, SeekOrigin.Begin);
         memS.Position=0;
         // считаем объект data двоичного формата из потока
         BinaryFormatter bf = new BinaryFormatter();
         memS.Position=0;
         data= (Data) bf.Deserialize(memS);
         memS.Close();
      }
      public void SerializeDataToFile() // сериализация в файл
      {
         // создаем поток для записи
         FileStream fs = File.Create("temp.dat");
         // помещаем данные в поток в двоичном формате
         BinaryFormatter bf = new BinaryFormatter();
         fs.Seek(0,SeekOrigin.Begin);
         bf.Serialize(fs, data);
         fs.Close();
         
      }
      
      public void DeserializeDataFromFile() // десериализация из файла
      {
         // создаем поток для записи
         FileStream fs1 = File.Open("temp.dat",FileMode.Open);
         // помещаем данные в поток в двоичном формате
         BinaryFormatter bf = new BinaryFormatter();
         fs1.Seek(0,SeekOrigin.Begin);
         data= (Data)bf.Deserialize(fs1);
         fs1.Close();
         
      }
      
   }   
//-----------------------------------------------         


}

Оффлайн axe

  • Старожил
  • *
  • Сообщений: 1203
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #6 : 06 Октября 2009, 14:26:25 »
Вечером постараюсь показать пример того, о чем я говорю.

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #7 : 07 Октября 2009, 14:14:41 »
Проблему решил, но не красиво.
Пришлось использовать BinaryReader и BinaryWriter без сериализации.
Но есть плюсы от такого решения. Количество передаваемой информации в пакете почти в 5 раз меньше.
Минусы - больше работать руками (не сразу вся структура махом передается, а все по тегу), что для больших объемов  информации утомляет (количество тегов может быть от 15000 до 5000 в реальной АСУТП) .
Проблему надо решать, когда будет поспокойнее.

Пользователь решил продолжить мысль 07 Октября 2009, 14:42:06:
Придумал, как решить проблему с набивкой программ при большом количестве тегов.
Набивается один файл, а все остальные генерятся скриптом. После чего вставляются в модули.
Неплохое решение.
« Последнее редактирование: 07 Октября 2009, 14:42:06 от alexander.pronin »

Оффлайн wl

  • Старожил
  • *
  • Сообщений: 1393
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #8 : 07 Октября 2009, 14:56:48 »
Придумал, как решить проблему с набивкой программ при большом количестве тегов.
Набивается один файл, а все остальные генерятся скриптом. После чего вставляются в модули.
Неплохое решение.

А может, посмотреть в сторону DLR и IronPython?
Это позволило бы генерировать текст прямо на ходу.

Не вникал, честно говоря, в Вашу проблему, но совсем недавно видел вот такую статью:
http://remark.wordpress.com/articles/configuration-with-ironpython/
http://ironpython-urls.blogspot.com/2009/09/configuration-with-ironpython.html
« Последнее редактирование: 07 Октября 2009, 14:59:47 от wl »
На свете феньки есть такие, брат Горацио, которых лохи просто не секут. (Шекспир, "Гамлет", вольный перевод)

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Вопрос по моно.
« Ответ #9 : 09 Октября 2009, 12:16:33 »
Теперь возник еще вопрос по моно. Чтобы не плодить темы задаю вопрос здесь.
Появится ли работающий конектор mono под mySQL для Ubuntu 8.10 в репах или нет.

 

Страница сгенерирована за 0.069 секунд. Запросов: 25.