2014-11-18 6 views
0

Создаю TcpClient с IPEndpoint и откройте NetworkStream с открытым соединением.BinaryFormatter десериализует несколько объектов из потока

stream = client.GetStream(); 

поток определяется как NetworkStream и клиента как TcpClient. Я хочу использовать Stream для отправки сериализованных объектов каждую секунду. Для этого у меня есть таймер, который отправляет каждую секунду через BinaryFormatter.

formatter.Serialize(stream, object); 

Объект в этом случае представляет собой сериализованный класс. С другой стороны, Я использую TcpListener и получить поток с

stream = listener.AcceptTcpClient().GetStream(); 

недо этот момент все работает как задумано. У первого объекта есть информация, которую я хочу, и я даже могу получить доступ к этой информации. Как только я хочу получить второй объект из одного потока, я получаю NullReferenceException.

streamObject = deserialiser.Deserialize(stream); 

Я не deserialize для определенного типа, поэтому я мог бы фильтровать объекты и запускать различные методы. * Обратите внимание, что я использую два разных класса для отправки и получения и оба класса работают в разных программах.

Мой вопрос: можно ли отправлять несколько объектов через один и тот же поток с интервалом между ними и десериализовать его с другой стороны, не открывая и не закрывая поток каждый раз?

* Некоторая дополнительная информация:

Таймер работает в Windowsservice как Thread. Первый объект будет отправлен, как указано выше, но второй объект не будет.

Как вы спрашиваете, это стек, который я получаю.

Вот мой метод Page_Load, как и было задано.

защищенный void Page_Load (отправитель объекта, EventArgs e) { recive = new ServerRecive(); recive.ReciveStreamObject(); FirstDate.Text = recive.ui.serverName; }

Соединение открыто, как только я определяю recive. А вот код для всего класса ServerRecive.

public class ServerRecive 
{ 
public ObjectTypeUI ui {get; set;} 
public ObjectTypeSI si { get; set; } 
public ObjectTypeDI di { get; set; } 

TcpListener listener; 
NetworkStream stream; 

BinaryFormatter deserialiser; 

public ServerRecive() 
{ 
deserialiser = new BinaryFormatter(); 
Initialize(); 
} 

private void Initialize() 
{ 
listener = new TcpListener (IPAddress.Any, *port*); 
listener.Start(); 
stream = listener.AcceptTcpClient().GetStream(); 
} 


public void ReciveStreamObject() 
{ 
object Object = new object(); 
try 
{ 
    Object = deserialiser.Deserialize(stream); 
} 
catch (Exception e) {} 

if (Object.GetType() == typeof(ObjectTypeSI)) 
{ 
    si = (ObjectTypeSI)Object; 
} 
else if (Object.GetType() == typeof(ObjectTypeUI)) 
{ 
    ui = (ObjectTypeUI)Object; 
} 
else if(Object.GetType() == typeof(ObjectTypeDI)) 
{ 
    di = (ObjectTypeDI)Object; 
} 
} 
} 

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

@nelus Я сделал некоторое обходное решение, чтобы получить Исключение. Теперь я RECIVED это исключение

System.Runtime.Serialization.SerializationException was not handled. 
HResult=-2146233076 
Message=The input stream is not a valid binary format. The start content  
(in  Bytes) is: 1B-65-72-69-61-6C-4F-62-6A-65-63-74-2E-53-65-72-76 ... 
Source=mscorlib 
StackTrace: 
at 

System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input) 
    at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord() 
    at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run() 
    at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 
    at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 
    at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream) 
    at System_GUI.ServerRecive.ReciveStreamObject() in c:\Users\rbr\Documents\Visual Studio 2012\WebSites\System_GUI\App_Code\Netzwerk\ServerRecive.cs:Zeile 51. 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 
InnerException: 
+0

Это будет легче помочь, если вы предоставите подробную информацию об исключении, особенно трассировку стека. – neleus

+0

Конечно, трассировка стека не так уж полезна без фактического кода, т. Е. Метода 'Page_Load()', и точно указывая, какая ссылка объекта равна нулю. –

+0

Вы повторно открываете соединение каждый раз или оно открыто и остается открытым? Если он остается открытым - как вы определяете границы объекта? – TGlatzer

ответ

0

Так что я построил второй проект, чтобы проверить, если мой сервер даже данные и Получать используется анализатор пакетов на локальном хосте, чтобы подтвердить это. Класс, который я теперь использую для восстановления, ничего больше не делал. Только то, что у него есть цикл while, который десериализует поток снова и снова. Это решило мою проблему.Похоже, что BinaryFormatter может искать объекты в потоке и десериализовать каждый объект, не зная фактического размера или положения объекта.

class Program 
{ 
    TcpListener listener = new TcpListener(IPAddress.Any, 4456); 
    NetworkStream stream; 

    ObjectTypeUI ui; 
    ObjectTypeDI di; 
    ObjectTypeSI si; 

    BinaryFormatter deserializer = new BinaryFormatter(); 

    public Program() 
    { 

    listener.Start(); 
    stream = listener.AcceptTcpClient().GetStream(); 
    while (true) 
    { 
     object streamObject = deserializer.Deserialize(stream); 

     if (streamObject.GetType() == typeof(ObjectTypeSI)) 
     { 
      si = (ObjectTypeSI)streamObject; 
      Console.WriteLine(si.Kunde); 
     } 
     else if (streamObject.GetType() == typeof(ObjectTypeUI)) 
     { 
      ui = (ObjectTypeUI)streamObject; 
      Console.WriteLine(ui.CpuUsage); 
     } 
     else if(streamObject.GetType() == typeof(ObjectTypeDI)) 
     { 
      di = (ObjectTypeDI)streamObject; 
     } 
    } 


    } 

    static void Main(string[] args) 
    { 
    new Program(); 
    Console.ReadLine(); 
    } 
} 

Актуальной проблемой является не то, как я получаю объекты, ни способ десериализации их. Проблема заключается в том, что Windowsservice фактически отменяет поток, который я использую для отправки моих объектов.

Так огромное спасибо @neleus и @ Grumbler85, которые помогли мне найти настоящую проблему.

 Смежные вопросы

  • Нет связанных вопросов^_^