Навигация
· XNA FAQ
· С чего начать
· Конкурсы
· Обратная связь
· XNA Блоги
Сейчас на сайте
· Гостей: 1

· Пользователей: 0

· Всего пользователей: 3,684
· Новый пользователь: headron
Последние фото
Эх, чуть не проспал закрытие.
Эх, чуть не проспал ...
Альбом: XNA Engine

GB
GB
Альбом: XNA Engine

South Park Coon & Friends
South Park Coon & Fr...
Альбом: XNA Games

Блоги
yavshoke
» XboxOne - интерес...
dampirik
» Push уведомления ...
dampirik
» Реклама,статистик...
Chort
» XNA и StartCoroutine
Chort
» Curve Class
dampirik
» Реклама, статисти...
dampirik
» Увеличение скорос...
dampirik
» Реклама, статисти...
general
» Распаковка DxtCom...
general
» Как работать с XN...
Поддержка
microsoft.com
1gb.ru - Дом для вашего сайта
Статистика посещений:

Просмотр темы
 Распечатать тему
Tcp Сервер - Клиент обмен данными
CSharpCraft
#1 Распечатать сообщение
Опубликовано 25.10.2013 17:44:40
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Ситуация такая: есть Tcp клиент и сервер для xna игры. Реализован обмен объектами, которые содержатся в единой библиотеке. Объекты сериализируются в массив байтов в точке отправки (с помощью BinaryFormatter) и десериализируются в точке приема.

Если объекты имеют небольшой размер, то все нормально. А если я, например, хочу отправить пользователю его аккаунт после входа (там массивы + много данных) то возникают исключения при десириализации (причем самые разные).

Сериализатор:
Загрузить источник  GeSHi: C#
  1. public static class SeriaizeHelper
  2. {
  3. /// <summary>
  4. /// Преобразует указанный объект в массив байт
  5. /// </summary>
  6. public static byte[] Serialization(IPacketType obj)
  7. {
  8. BinaryFormatter formatter = new BinaryFormatter();
  9. using (MemoryStream stream = new MemoryStream())
  10. {
  11. formatter.Serialize(stream, obj);
  12. byte[] msg = stream.ToArray();
  13. stream.Close();
  14. return msg;
  15. }
  16. }
  17.  
  18. /// <summary>
  19. /// Преобразует массив байт в объект
  20. /// </summary>
  21. public static IPacketType DeSerialization(byte[] serializedAsBytes)
  22. {
  23. using (MemoryStream stream = new MemoryStream(serializedAsBytes))
  24. {
  25. BinaryFormatter formatter = new BinaryFormatter();
  26. stream.Position = 0;
  27. var returnable = (IPacketType)formatter.Deserialize(stream);
  28. stream.Close();
  29. return returnable;
  30. }
  31. }
  32. }
  33.  
Добавлено за 0.009 секунд, используя GeSHi 1.0.8.2


Сегмент кода отправки данных (одинаково на сервере и в клиенте):
Загрузить источник  GeSHi: C#
  1. public void Write(IPacketType packet)
  2. {
  3. if (isConnected)
  4. {
  5. int bytesSent = socket.Send(SeriaizeHelper.Serialization((IPacketType)packet)); // < ОТПРАВКА ДАННЫХ !
  6. }
  7. else throw new ArgumentOutOfRangeException();
  8. }
  9.  
Добавлено за 0.005 секунд, используя GeSHi 1.0.8.2


Сегмент кода приема данных (одинаково на сервере и в клиенте):
Загрузить источник  GeSHi: C#
  1.  
  2. byte[] bytes = new byte[16000]; //РАЗМЕР ПАКЕТОВ НЕ ПРЕВЫШАЕТ ЭТОГО !
  3. int bytesRec = client.socket.Receive(bytes);
  4. IPacketType input = (IPacketType)SeriaizeHelper.DeSerialization(bytes);
  5.  
Добавлено за 0.005 секунд, используя GeSHi 1.0.8.2


IPacketType - интерфейс для всех объектов, которые я отправляю.

Может использовать другой способ, или как то переделать то, что есть сейчас? Как решить эту проблему? Основная задача именно в отправки объектов c# с любым содержанием (в пределах разумного) по сети
 
dampirik
#2 Распечатать сообщение
Опубликовано 25.10.2013 18:22:26
Аватар пользователя

Ветеран


Сообщений: 957
Зарегистрирован: 21.02.10

Я как понимаю проблема в
возникают исключения при десириализации
?
а) Попробуйте сравнить то, что отправили и то что получили.
б) Если объём превышает 16кб то все… Советую в первые скажем 4 байта отправлять длину пакета и получать соответственно сперва 4 байта из сети, а потом остальное исходя из этой длины.

 
CSharpCraft
#3 Распечатать сообщение
Опубликовано 25.10.2013 19:21:18
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

dampirik написал:
Я как понимаю проблема в
возникают исключения при десириализации
?


В частности <Отсутствует идентификатор сборки для типа объекта "WOS.SingleNetLibary.SingleGameObjects.ServerSailUsedData".>

dampirik написал:
Попробуйте сравнить то, что отправили и то что получили


Выходящий массив байт и входящий одинаковы (за исключением 16000 - N пустых байт).

dampirik написал:
Если объём превышает 16кб то все… Советую в первые скажем 4 байта отправлять длину пакета и получать соответственно сперва 4 байта из сети, а потом остальное исходя из этой длины.


Там получается максимум 4 - 6 кб. А 16кб это ограничение TCP или можно как-то переделать?

P.S. Пакеты попроще отправляются и принимаются отлично.
 
CSharpCraft
#4 Распечатать сообщение
Опубликовано 25.10.2013 20:51:49
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Если нужно могу скинуть в личку сервер (+ лаунчер) / клиент / единую библиотеку объектов
 
dampirik
#5 Распечатать сообщение
Опубликовано 25.10.2013 21:17:42
Аватар пользователя

Ветеран


Сообщений: 957
Зарегистрирован: 21.02.10

Выходящий массив байт и входящий одинаковы (за исключением 16000 - N пустых байт).

Ну дк уберите пустые байты, если проблема останется, то посмотрите, что не так в использовании BinaryFormatter…Поиграйтесь без отправки по сети
 
CSharpCraft
#6 Распечатать сообщение
Опубликовано 25.10.2013 21:36:08
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Спасибо, проблема действительно в лишних байтах. Хотя, маленькие пакеты отправляются хорошо (даже учитывая эти байты). Нужно отправлять размер буфера, а потом пакет. Хотя это очень много головной боли...
 
Hellmapper
#7 Распечатать сообщение
Опубликовано 25.10.2013 22:35:53
Аватар пользователя

Старший специалист


Сообщений: 440
Зарегистрирован: 03.07.11

А что мешает запихнуть все в 1 пакет? Первые 4 байта - количество последующих, затем байты с контентом.
 
CSharpCraft
#8 Распечатать сообщение
Опубликовано 26.10.2013 11:52:20
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Hellmapper написал:
А что мешает запихнуть все в 1 пакет? Первые 4 байта - количество последующих, затем байты с контентом.


А хотя да, вы правы. Прочитать сначала первые четыре байта, а затем выделить соответствующий буфер и прочитать все до конца.
 
CSharpCraft
#9 Распечатать сообщение
Опубликовано 26.10.2013 12:19:15
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Все сделал. Но проблема осталась:

Дополнительные сведения: Отсутствует идентификатор сборки для типа объекта "WOS.SingleNetLibary.SingleGameObjects.ServerSailUsedData".

Финальный массив байт отправляемый на клиенте и принимаемый на сервере идентичен (первые четыре байта при отправке добавляю, при приеме удаляю). Для отправки данных используются классы, которые находятся в единой библиотеке (а та подключена и к клиенту и к серверу). Сериализатор тоже находится в ней. В чем может быть проблема?
 
Hellmapper
#10 Распечатать сообщение
Опубликовано 26.10.2013 12:22:50
Аватар пользователя

Старший специалист


Сообщений: 440
Зарегистрирован: 03.07.11

А добавляете в начало массива?
 
dampirik
#11 Распечатать сообщение
Опубликовано 26.10.2013 12:25:08
Аватар пользователя

Ветеран


Сообщений: 957
Зарегистрирован: 21.02.10

dampirik написал:
Поиграйтесь без отправки по сети


Я с ним не разу не работал, поэтому не чего сказать не могу…
Если скорость не критичная, стерилизуй в json или в XML, а потом енкодинг в байты.
 
CSharpCraft
#12 Распечатать сообщение
Опубликовано 26.10.2013 12:50:12
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Hellmapper написал:
А добавляете в начало массива?


Да. В результате перед десериализацией все равно получается такой же массив, как я отправлял (только без байтов в начале). Такой же длинны, и с такими же байтами.

П.С. Я отправляю этот пакет с клиента на сервер
Изменил(а) CSharpCraft, 26.10.2013 12:54:31
 
CSharpCraft
#13 Распечатать сообщение
Опубликовано 26.10.2013 13:50:04
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

В пределах одного решения все конвертится туда / обратно без проблем (без отправки по сети). По сети байты получаются такие же, как и при отправке, соответственно проблема не в отправке.
 
Hellmapper
#14 Распечатать сообщение
Опубликовано 26.10.2013 14:01:10
Аватар пользователя

Старший специалист


Сообщений: 440
Зарегистрирован: 03.07.11

Попробуйте написать свой сериализатор (и десериализатор), который создает массив байтов из класса по типу: длина послед байтов - байты. А на сервере считывать их по этому же принципу.
 
CSharpCraft
#15 Распечатать сообщение
Опубликовано 26.10.2013 14:20:47
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

Hellmapper написал:
Попробуйте написать свой сериализатор (и десериализатор), который создает массив байтов из класса по типу: длина послед байтов - байты. А на сервере считывать их по этому же принципу.


Это как? У меня много разных типов классов с разным набором параметров (в том числе массивы)
Изменил(а) CSharpCraft, 26.10.2013 14:21:09
 
dampirik
#16 Распечатать сообщение
Опубликовано 26.10.2013 15:10:19
Аватар пользователя

Ветеран


Сообщений: 957
Зарегистрирован: 21.02.10

Это как?

Если одним словом, геморно
Судя по задачи, речи нету использовать исключительно бинарную сериализацию.. погляди в сторону XML/JSON
 
CSharpCraft
#17 Распечатать сообщение
Опубликовано 26.10.2013 21:25:56
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

XmlSerializer плюется еще при попытке сериализации:
{"Тип WOS.SingleNetLibary.Packets.OnLoginMsg не ожидался. Используйте атрибут XmlInclude или SoapInclude для задания типов, которые не известны как статические."}

Код классов:
Загрузить источник  GeSHi: C#
  1.  
  2. [XmlInclude(typeof(IPacketType))]
  3. public abstract class IPacketType
  4. {
  5. /// <summary>
  6. /// Возвращает напарвление, по которому может следовать пакет
  7. /// </summary>
  8. [XmlIgnore]
  9. public abstract FlowOfPack Flow { get; }
  10.  
  11. public IPacketType()
  12. {
  13.  
  14. }
  15. }
  16.  
Добавлено за 0.005 секунд, используя GeSHi 1.0.8.2

Загрузить источник  GeSHi: C#
  1.  
  2. [Serializable]
  3. [XmlInclude(typeof(OnLoginMsg))]
  4. public class OnLoginMsg : IPacketType
  5. {
  6. [XmlIgnore]
  7. public override FlowOfPack Flow
  8. {
  9. get
  10. {
  11. return FlowOfPack.FromClientToServer;
  12. }
  13. }
  14.  
  15. /// <summary>
  16. /// Логин
  17. /// </summary>
  18. public string Login;
  19. /// <summary>
  20. /// Пароль
  21. /// </summary>
  22. public string Passworld;
  23. /// <summary>
  24. /// TRUE: Не выполнять проверку и добавить данные в базу данных
  25. /// </summary>
  26. public bool IsCreateNew;
  27.  
  28. public OnLoginMsg()
  29. {
  30.  
  31. }
  32.  
  33. public OnLoginMsg(string login, string password, bool isCreateNew)
  34. {
  35. Login = login;
  36. Passworld = password;
  37. IsCreateNew = isCreateNew;
  38. }
  39. }
  40.  
Добавлено за 0.008 секунд, используя GeSHi 1.0.8.2

Изменил(а) CSharpCraft, 26.10.2013 21:36:03
 
CSharpCraft
#18 Распечатать сообщение
Опубликовано 27.10.2013 10:16:18
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

JSON сериализация:

Не удалось привести тип объекта "System.Object" к типу "WOS.SingleNetLibary.Packets.IPacketType".
 
general
#19 Распечатать сообщение
Опубликовано 27.10.2013 11:59:28
Аватар пользователя

Администратор сайта


Сообщений: 3788
Зарегистрирован: 10.02.09

а ты не правильно используешь JSON.
он хорош, но не волшебный.

в JSON класс для сериализации
- должен содержать только поля (похож на структуру)
- не нужны атрибуты
- есть моменты которые не умеет разбирать, но мелкие.

вот пример:
Загрузить источник  GeSHi: C#
  1. public class SaveUnit
  2. {
  3. #if DEBUG
  4. public string Name;
  5. #endif
  6. public int MapX;
  7. public int MapY;
  8. public Vector2 MoveDirection;
  9. public int HitPoints;
  10. public int TargetID;
  11. public Unit.UnitPlayer Player;
  12. public Unit.UnitType Type;
  13. public Unit.UnitModel Model;
  14. public bool PowerOn;
  15. public int Upgrade;
  16. }
  17.  
Добавлено за 0.006 секунд, используя GeSHi 1.0.8.2


по этому не бери рабочие классы, а сделай отдельные,
в которых подготавливаешь данные для сериализации.
это сделает процесс более управляемым, а пакеты короче.
[dreamteam-mobile]
[dtimofeev.blogspot.com][c#][XNA][blog]
 
CSharpCraft
#20 Распечатать сообщение
Опубликовано 27.10.2013 12:26:46
Аватар пользователя

Специалист


Сообщений: 190
Зарегистрирован: 27.03.13

general написал:
- должен содержать только поля (похож на структуру)

Да

general написал:
не нужны атрибуты

Да

general написал:
по этому не бери рабочие классы, а сделай отдельные

А это и есть отдельные

Тут наверное какая-то проблема другая, раз не один сериализатор работать не хочет. Все классы простые, я даже пробовал убирать наследование и оставить только поля. В таком режиме работает только BinaryFormatter, и то когда объем данных небольшой. Может там накладки с различной версией сборок, или еще с чем то?
Изменил(а) CSharpCraft, 27.10.2013 12:30:14
 
Перейти на форум:
Авторизация
Логин

Пароль



Вы не зарегистрированы?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Мини-чат
Вы должны авторизироваться, чтобы добавить сообщение.

27.08.2014
Я умею немного на asp.net + html и css

22.08.2014
на ASP mvc 3 есть пару проектов. Могу помочь, если нужно. Обидно, если закроется Frown

21.08.2014
я тоже ноль

21.08.2014
Я в вебе только с php занимался да и то на уровне чтоб работало.

21.08.2014
Я в вебе полный ноль…

21.08.2014
Переводить его надо, хоть на ту же азуру. И двиг менять на что-то современное. Если есть веб-разрабы - можем скооперироваться. Один делать не буду.

21.08.2014
не знаю всех нюансов по оплате и все хорошее когда нибудь заканчивается

21.08.2014
А что случилось?

21.08.2014
похоже сайт будет работать до 28го числа

09.08.2014
Апи пока не видел. Но есть приложение в магазине Live Lock Screen BETA, так что думаю скоро будет

08.08.2014
Я про API для Update1. На нем работает это

08.08.2014
А что именно нужно? Чтото и сейчас открыто http://msdn.micro.
...105).aspx

06.08.2014
Кто-нибудь слышал об открытии доступа к Lock Screen Api?

31.07.2014
VPDExpress на базе MVS 2012, ни в какую не ловит исключения. Даже если их сам создаешь. И всех так?

25.07.2014
С днем системного администратора причастных к этой профессии! По случаю - тортик от жены

RSS каналы сайта
XNA - Новости
XNA - Статьи
XNA - Форум
XNA - Галерея
XNA - Файлы
Время загрузки: 0,50 секунд 8,709,468 уникальных посетителей