public void ClientMain() { TcpClient connection = null; bool done = false; try { connection = new TcpClient( this.Address, this.Port ); var networkStream = connection.GetStream(); new Thread( delegate() { try { BinaryReader reader = new BinaryReader( networkStream ); BinaryFormatter inputFormat = new BinaryFormatter(); // we need some connection every 60 minutes, the host should be trying to request progress networkStream.ReadTimeout = Timeout.Infinite; while ( !done || this.Exit ) { var msg = new Message( (MessageType)reader.ReadInt32() ); switch ( msg.Type ) { case MessageType.RequestProgress: { msg.Type = MessageType.PostProgess; this.Messages.Add( msg ); } break; case MessageType.ReturningResource: { var name = reader.ReadString(); bool exists = reader.ReadBoolean(); object data = null; if ( exists ) { data = inputFormat.Deserialize( reader.BaseStream ); } Result res = new Result() { Name = name, Data = data }; msg.Data = res; this.Messages.Add( msg ); } break; case MessageType.PostCancel: { this.Messages.Add( msg ); } break; case MessageType.SendModelSystem: { var length = reader.ReadInt32(); byte[] data = new byte[length]; var soFar = 0; while ( soFar < length ) { soFar += reader.Read( data, soFar, length - soFar ); } msg.Data = data; this.Messages.Add( msg ); } break; case MessageType.Quit: { done = true; this.Exit = true; Console.WriteLine( "Exiting." ); } break; case MessageType.SendCustomMessage: { // Time to receive a new custom message var number = reader.ReadInt32(); var length = reader.ReadInt32(); var buff = new byte[length]; MemoryStream buffer = new MemoryStream( buff ); int soFar = 0; while ( soFar < length ) { soFar += reader.Read( buff, soFar, length - soFar ); } this.Messages.Add( new Message( MessageType.ReceiveCustomMessage, new ReceiveCustomMessageMessage() { CustomMessageNumber = number, Stream = buffer } ) ); } break; default: { // We don't know how to deal with this done = true; this.Exit = true; Console.WriteLine( "Came across a message number " + msg.Type + " not sure what to do with it. Exiting." ); } break; } Thread.MemoryBarrier(); } } catch ( IOException ) { done = true; Thread.MemoryBarrier(); this.Exit = true; Console.WriteLine( "Host has disconnected Client" ); Environment.Exit( 0 ); } catch ( Exception e ) { done = true; Console.WriteLine( "Client exception" ); Console.WriteLine( e.Message ); Console.WriteLine( e.StackTrace ); } finally { Console.WriteLine("Client reader has exited."); connection.Close(); done = true; this.Exit = true; Thread.MemoryBarrier(); } } ).Start(); BinaryWriter writer = new BinaryWriter( networkStream ); BinaryFormatter outputFormat = new BinaryFormatter(); networkStream.WriteTimeout = 20000; while ( !done && !this.Exit ) { var message = this.Messages.GetMessageOrTimeout( 200 ); Thread.MemoryBarrier(); if ( !done && message != null ) { var exit = ProcessMessage( writer, outputFormat, message ); if ( exit ) { done = true; } } } } catch ( Exception e ) { Console.WriteLine( e.Message ); Console.WriteLine( e.StackTrace ); } finally { if ( connection != null ) { connection.Close(); } done = true; } done = true; this.Exit = true; }
private bool ProcessMessage(BinaryWriter writer, BinaryFormatter outputFormat, Message message) { switch ( message.Type ) { case MessageType.PostComplete: { writer.Write( (Int32)MessageType.PostComplete ); } break; case MessageType.PostResource: { var data = message.Data as Result; writer.Write( data.Name ); outputFormat.Serialize( writer.BaseStream, data.Data ); } break; case MessageType.PostProgess: { writer.Write( (Int32)MessageType.PostProgess ); writer.Write( this.Progress ); writer.Flush(); } break; case MessageType.RequestResource: { var dr = message.Data as DelayedResult; this.ResourceRequests.AddLast( dr ); writer.Write( (Int32)MessageType.RequestResource ); writer.Write( dr.Name ); writer.Flush(); } break; case MessageType.ReturningResource: { var result = message.Data as Result; DelayedResult toRemove = null; foreach ( var delayed in this.ResourceRequests ) { if ( delayed.Name == result.Name ) { toRemove = delayed; delayed.Data = result.Data; delayed.Lock.Release(); break; } } if ( toRemove != null ) { ResourceRequests.Remove( toRemove ); } } break; case MessageType.PostCancel: { var ms = this.CurrentRunningModelSystem; // if we don't have a model system then we are done if ( ms == null ) break; try { // try to cancel the model system ms.ExitRequest(); } catch { } } break; case MessageType.SendModelSystem: { try { var mssBuff = message.Data as byte[]; IModelSystemStructure mss = null; using ( MemoryStream memory = new MemoryStream() ) { memory.Write( mssBuff, 0, mssBuff.Length ); memory.Position = 0; mss = ModelSystemStructure.Load( memory, this.Configuration ); } if ( this.ModelSystemThread != null && this.ModelSystemThread.IsAlive ) { try { this.ModelSystemThread.Abort(); } catch { } } // now that the other thread is going to end // we can now go and start generating ourselves // in another run thread ( this.ModelSystemThread = new Thread( ModelSystemStartup ) ).Start( mss ); } catch ( Exception e ) { Console.WriteLine( e.ToString() ); return true; } } break; case MessageType.SendCustomMessage: { var msg = message.Data as SendCustomMessageMessage; int msgNumber = msg.CustomMessageNumber; int length = 0; var failed = false; byte[] buffer = null; Action<object, Stream> customConverter; bool getConverter = false; lock ( this ) { getConverter = this.CustomSenders.TryGetValue( msgNumber, out customConverter ); } if ( getConverter ) { using ( MemoryStream mem = new MemoryStream( 0x100 ) ) { try { customConverter( msg.Data, mem ); mem.Position = 0; buffer = mem.ToArray(); length = buffer.Length; } catch { failed = true; } } } writer.Write( (Int32)MessageType.SendCustomMessage ); writer.Write( (Int32)msg.CustomMessageNumber ); writer.Write( (Int32)length ); if ( !failed ) { writer.Write( buffer, 0, length ); buffer = null; } } break; case MessageType.ReceiveCustomMessage: { var msg = message.Data as ReceiveCustomMessageMessage; var customNumber = msg.CustomMessageNumber; Func<Stream, object> customConverter; bool getConverted = false; lock ( this ) { getConverted = this.CustomReceivers.TryGetValue( customNumber, out customConverter ); } if ( getConverted ) { using ( var stream = msg.Stream ) { try { object output = customConverter( stream ); List<Action<object>> handlers; if ( this.CustomHandlers.TryGetValue( msg.CustomMessageNumber, out handlers ) ) { foreach ( var handler in handlers ) { try { handler( output ); } catch (Exception e) { Console.WriteLine( e.Message + "\r\n" + e.StackTrace ); } } } } catch { } } } } break; default: { // FAIL! Console.WriteLine( "Processing a message of type " + message.Type + " and we didn't know what to do with it." ); return true; } } return false; }