} // private void LoopRead() { while (!_ExitLoop) { try { ProtoBufExample.Header lHeader = ProtoBuf.Serializer.DeserializeWithLengthPrefix <ProtoBufExample.Header>(_NetworkStream, ProtoBuf.PrefixStyle.Fixed32); if (lHeader == null) { break; } if (lHeader.objectType == ProtoBufExample.eType.eError) { ProtoBufExample.ErrorMessage lErrorMessage = ProtoBuf.Serializer.DeserializeWithLengthPrefix <ProtoBufExample.ErrorMessage>(_NetworkStream, ProtoBuf.PrefixStyle.Fixed32); lHeader.data = lErrorMessage; } _PendingFeedbacks.Remove(lHeader); } catch (System.IO.IOException) { if (_ExitLoop) { Console.WriteLine("user requested client shutdown"); } else { Console.WriteLine("disconnected"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } Console.WriteLine("client: reader is shutting down"); } //
public static void Test() { NetworkListener lServer = new NetworkListener("127.0.0.1", 65432, "Server"); NetworkClient lClient = new NetworkClient("127.0.0.1", 65432, "Client"); lServer.Connect(); lServer.OnMessageBook += new NetworkListener.dOnMessageBook(OnMessageBook); lServer.OnMessageFable += new NetworkListener.dOnMessageFable(OnMessageFable); lClient.Connect(); ProtoBufExample.Header lHeader; // send a book across the network ProtoBufExample.Book lBook = ProtoBufExample.GetData(); lHeader = new ProtoBufExample.Header(lBook, ProtoBufExample.eType.eBook); lClient.Send(lHeader); System.Threading.Thread.Sleep(1000); // remove this to see the asynchonous processing (the output will look terrible) // send a fable across the network lHeader = new ProtoBufExample.Header(lBook.stories[1], ProtoBufExample.eType.eFable); lClient.Send(lHeader); System.Threading.Thread.Sleep(1000); lClient.Disconnect(); lServer.Disconnect(); Console.ReadLine(); }
} // public static void Send(TcpClient xClient, ProtoBufExample.Header xHeader) { if (xHeader == null) { return; } if (xClient == null) { return; } lock (xClient) { try { NetworkStream lNetworkStream = xClient.GetStream(); // send header (most likely a simple feedback) ProtoBuf.Serializer.SerializeWithLengthPrefix <ProtoBufExample.Header>(lNetworkStream, xHeader, ProtoBuf.PrefixStyle.Fixed32); // send errors if (xHeader.objectType != ProtoBufExample.eType.eError) { return; } ProtoBuf.Serializer.SerializeWithLengthPrefix <ProtoBufExample.ErrorMessage>(lNetworkStream, (ProtoBufExample.ErrorMessage)xHeader.data, ProtoBuf.PrefixStyle.Fixed32); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } //
} // public void Remove(ProtoBufExample.Header xHeader) { ProtoBufExample.Header lHeader; if (!_Messages.TryRemove(xHeader.serialMessageId, out lHeader)) { throw new Exception("there must be a programming error somewhere"); } switch (xHeader.objectType) { case ProtoBufExample.eType.eError: Console.WriteLine("error: " + ((ProtoBufExample.ErrorMessage)xHeader.data).Text); Console.WriteLine("the message that was sent out was: " + lHeader.objectType + " with serial id " + lHeader.serialMessageId); Console.WriteLine("please check the log files" + Environment.NewLine); break; case ProtoBufExample.eType.eFeedback: // all ok ! break; default: Console.WriteLine("warning: This message type was not expected."); break; } } //
} // public void Send(ProtoBufExample.Header xHeader) { if (xHeader == null) { return; } _PendingFeedbacks.Add(xHeader); _Queue.Add(xHeader); } //
public void Add(ProtoBufExample.Header xHeader) { if (xHeader == null) { throw new Exception("cannot add a null header"); } if (!_Messages.TryAdd(xHeader.serialMessageId, xHeader)) { throw new Exception("there must be a programming error somewhere"); } } //
// demo: synchronous processing static void OnMessageFable(TcpClient xSender, ProtoBufExample.Header xHeader, ProtoBufExample.Fable xFable) { Console.WriteLine(Environment.NewLine + "received a fable: "); Console.WriteLine(xFable.ToString()); // demo: we tell the server that something went wrong ProtoBufExample.ErrorMessage lErrorMessage = new ProtoBufExample.ErrorMessage() { Text = "The fable was rejected. It is far too short." }; ProtoBufExample.Header lErrorHeader = new ProtoBufExample.Header(lErrorMessage, ProtoBufExample.eType.eError, xHeader.serialMessageId); NetworkListener.Send(xSender, lErrorHeader); } //
} // // demo: asynchronous processing static void OnMessageBook(TcpClient xSender, ProtoBufExample.Header xHeader, ProtoBufExample.Book xBook) { Task.Factory.StartNew(() => { Console.WriteLine(Environment.NewLine + "received a book: "); Console.WriteLine(xBook.ToString()); // send a feedback without any body to signal all was ok ProtoBufExample.Header lFeedback = new ProtoBufExample.Header(null, ProtoBufExample.eType.eFeedback, xHeader.serialMessageId); NetworkListener.Send(xSender, lFeedback); return; }); Console.WriteLine("Book event was raised"); } //
} // private void LoopWrite() { while (!_ExitLoop) { try { ProtoBufExample.Header lHeader = _Queue.Take(); if (lHeader == null) { break; } // send header ProtoBuf.Serializer.SerializeWithLengthPrefix <ProtoBufExample.Header>(_NetworkStream, lHeader, ProtoBuf.PrefixStyle.Fixed32); // send data switch (lHeader.objectType) { case ProtoBufExample.eType.eBook: ProtoBuf.Serializer.SerializeWithLengthPrefix <ProtoBufExample.Book>(_NetworkStream, (ProtoBufExample.Book)lHeader.data, ProtoBuf.PrefixStyle.Fixed32); break; case ProtoBufExample.eType.eFable: ProtoBuf.Serializer.SerializeWithLengthPrefix <ProtoBufExample.Fable>(_NetworkStream, (ProtoBufExample.Fable)lHeader.data, ProtoBuf.PrefixStyle.Fixed32); break; default: break; } } catch (System.IO.IOException) { if (_ExitLoop) { Console.WriteLine("user requested client shutdown."); } else { Console.WriteLine("disconnected"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } _ExitLoop = true; Console.WriteLine("client: writer is shutting down"); } //
} // private void LoopRead(object xClient) { TcpClient lClient = xClient as TcpClient; NetworkStream lNetworkStream = lClient.GetStream(); while (!_ExitLoop) { try { ProtoBufExample.Header lHeader = ProtoBuf.Serializer.DeserializeWithLengthPrefix <ProtoBufExample.Header>(lNetworkStream, ProtoBuf.PrefixStyle.Fixed32); if (lHeader == null) { break; // happens during shutdown process } switch (lHeader.objectType) { case ProtoBufExample.eType.eBook: ProtoBufExample.Book lBook = ProtoBuf.Serializer.DeserializeWithLengthPrefix <ProtoBufExample.Book>(lNetworkStream, ProtoBuf.PrefixStyle.Fixed32); if (lBook == null) { break; } lHeader.data = lBook; // not necessary, but nicer dOnMessageBook lEventBook = OnMessageBook; if (lEventBook == null) { continue; } lEventBook(lClient, lHeader, lBook); break; case ProtoBufExample.eType.eFable: ProtoBufExample.Fable lFable = ProtoBuf.Serializer.DeserializeWithLengthPrefix <ProtoBufExample.Fable>(lNetworkStream, ProtoBuf.PrefixStyle.Fixed32); if (lFable == null) { break; } lHeader.data = lFable; // not necessary, but nicer dOnMessageFable lEventFable = OnMessageFable; if (lEventFable == null) { continue; } lEventFable(lClient, lHeader, lFable); break; default: Console.WriteLine("Mayday, mayday, we are in big trouble."); break; } } catch (System.IO.IOException) { if (_ExitLoop) { Console.WriteLine("user requested client shutdown"); } else { Console.WriteLine("disconnected"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } Console.WriteLine("server: listener is shutting down"); } //