From 5acdf3f768c69f809b34b51e77ae0c522eee299a Mon Sep 17 00:00:00 2001 From: JamJar00 Date: Wed, 8 Jun 2016 21:58:30 +0100 Subject: [PATCH] Various additions --- Hazel.UnitTests/TcpConnectionTests.cs | 29 +- Hazel.UnitTests/TestHelper.cs | 12 +- Hazel.UnitTests/UdpConnectionTests.cs | 41 ++- Hazel/Connection.cs | 20 +- Hazel/ConnectionListener.cs | 22 +- Hazel/DataEventArgs.cs | 12 +- Hazel/DisconnectedEventArgs.cs | 7 +- Hazel/DocInclude/common.xml | 14 +- .../Documentation/Content Layout.content | 11 + .../Documentation/Introduction.aml | 24 ++ .../Documentation/Quickstart.aml | 337 ++++++++++++++++++ .../Technical Details/Protocols/Protocols.aml | 14 + .../Technical Details/Protocols/TCP.aml | 33 ++ .../Technical Details/Protocols/UDP-RUDP.aml | 146 ++++++++ .../Technical Details/Technical Details.aml | 14 + Hazel/{ => Documentation}/Hazel.shfbproj | 27 +- Hazel/Hazel.csproj | 18 +- Hazel/NetworkEndPoint.cs | 11 +- Hazel/SendOption.cs | 6 +- Hazel/SendOptionInternal.cs | 6 +- Hazel/{ => Tcp}/StateObject.cs | 3 +- Hazel/{ => Tcp}/TcpConnection.cs | 63 ++-- Hazel/{ => Tcp}/TcpConnectionListener.cs | 4 +- Hazel/{ => Udp}/UdpClientConnection.cs | 41 +-- Hazel/{ => Udp}/UdpConnection.KeepAlive.cs | 2 +- Hazel/{ => Udp}/UdpConnection.Reliable.cs | 5 +- Hazel/{ => Udp}/UdpConnection.cs | 2 +- Hazel/{ => Udp}/UdpConnectionListener.cs | 2 +- Hazel/{ => Udp}/UdpServerConnection.cs | 8 +- 29 files changed, 776 insertions(+), 158 deletions(-) create mode 100644 Hazel/Documentation/Documentation/Content Layout.content create mode 100644 Hazel/Documentation/Documentation/Introduction.aml create mode 100644 Hazel/Documentation/Documentation/Quickstart.aml create mode 100644 Hazel/Documentation/Documentation/Technical Details/Protocols/Protocols.aml create mode 100644 Hazel/Documentation/Documentation/Technical Details/Protocols/TCP.aml create mode 100644 Hazel/Documentation/Documentation/Technical Details/Protocols/UDP-RUDP.aml create mode 100644 Hazel/Documentation/Documentation/Technical Details/Technical Details.aml rename Hazel/{ => Documentation}/Hazel.shfbproj (69%) rename Hazel/{ => Tcp}/StateObject.cs (90%) rename Hazel/{ => Tcp}/TcpConnection.cs (95%) rename Hazel/{ => Tcp}/TcpConnectionListener.cs (98%) rename Hazel/{ => Udp}/UdpClientConnection.cs (94%) rename Hazel/{ => Udp}/UdpConnection.KeepAlive.cs (99%) rename Hazel/{ => Udp}/UdpConnection.Reliable.cs (98%) rename Hazel/{ => Udp}/UdpConnection.cs (99%) rename Hazel/{ => Udp}/UdpConnectionListener.cs (99%) rename Hazel/{ => Udp}/UdpServerConnection.cs (92%) diff --git a/Hazel.UnitTests/TcpConnectionTests.cs b/Hazel.UnitTests/TcpConnectionTests.cs index 66d9958..ccdf314 100644 --- a/Hazel.UnitTests/TcpConnectionTests.cs +++ b/Hazel.UnitTests/TcpConnectionTests.cs @@ -3,6 +3,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Net; using System.Threading; +using Hazel.Tcp; + namespace Hazel.UnitTests { [TestClass] @@ -14,13 +16,14 @@ namespace Hazel.UnitTests [TestMethod] public void TcpFieldTest() { + NetworkEndPoint ep = new NetworkEndPoint(IPAddress.Loopback, 4296); + using (TcpConnectionListener listener = new TcpConnectionListener(IPAddress.Any, 4296)) - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(ep)) { listener.Start(); - NetworkEndPoint ep = new NetworkEndPoint(IPAddress.Loopback, 4296); - connection.Connect(ep); + connection.Connect(); //Connection fields Assert.AreEqual(ep, connection.EndPoint); @@ -39,11 +42,11 @@ namespace Hazel.UnitTests public void TcpIPv4ConnectionTest() { using (TcpConnectionListener listener = new TcpConnectionListener(IPAddress.Any, 4296, IPMode.IPv4)) - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4))) { listener.Start(); - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)); + connection.Connect(); } } @@ -57,14 +60,14 @@ namespace Hazel.UnitTests { listener.Start(); - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4))) { - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)); + connection.Connect(); } - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4AndIPv6))) { - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4AndIPv6)); + connection.Connect(); } } } @@ -76,7 +79,7 @@ namespace Hazel.UnitTests public void TcpServerToClientTest() { using (TcpConnectionListener listener = new TcpConnectionListener(IPAddress.Any, 4296)) - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunServerToClientTest(listener, connection, 4, 0, SendOption.FragmentedReliable); } @@ -89,7 +92,7 @@ namespace Hazel.UnitTests public void TcpClientToServerTest() { using (TcpConnectionListener listener = new TcpConnectionListener(IPAddress.Any, 4296)) - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunClientToServerTest(listener, connection, 4, 0, SendOption.FragmentedReliable); } @@ -102,7 +105,7 @@ namespace Hazel.UnitTests public void ClientDisconnectTest() { using (TcpConnectionListener listener = new TcpConnectionListener(IPAddress.Any, 4296)) - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunClientDisconnectTest(listener, connection); } @@ -115,7 +118,7 @@ namespace Hazel.UnitTests public void ServerDisconnectTest() { using (TcpConnectionListener listener = new TcpConnectionListener(IPAddress.Any, 4296)) - using (TcpConnection connection = new TcpConnection()) + using (TcpConnection connection = new TcpConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunServerDisconnectTest(listener, connection); } diff --git a/Hazel.UnitTests/TestHelper.cs b/Hazel.UnitTests/TestHelper.cs index 7434fbd..7334be3 100644 --- a/Hazel.UnitTests/TestHelper.cs +++ b/Hazel.UnitTests/TestHelper.cs @@ -37,7 +37,7 @@ namespace Hazel.UnitTests listener.Start(); //Setup conneciton - connection.DataReceived += delegate(object sender, DataEventArgs args) + connection.DataReceived += delegate(object sender, DataReceivedEventArgs args) { Trace.WriteLine("Data was received correctly."); @@ -51,7 +51,7 @@ namespace Hazel.UnitTests mutex.Set(); }; - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296)); + connection.Connect(); //Wait until data is received mutex.WaitOne(); @@ -76,7 +76,7 @@ namespace Hazel.UnitTests //Setup listener listener.NewConnection += delegate(object sender, NewConnectionEventArgs args) { - args.Connection.DataReceived += delegate(object innerSender, DataEventArgs innerArgs) + args.Connection.DataReceived += delegate(object innerSender, DataReceivedEventArgs innerArgs) { Trace.WriteLine("Data was received correctly."); @@ -99,7 +99,7 @@ namespace Hazel.UnitTests listener.Start(); //Connect - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296)); + connection.Connect(); connection.SendBytes(data, sendOption); //Wait until data is received @@ -132,7 +132,7 @@ namespace Hazel.UnitTests listener.Start(); - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296)); + connection.Connect(); mutex.WaitOne(); } @@ -156,7 +156,7 @@ namespace Hazel.UnitTests listener.Start(); - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296)); + connection.Connect(); connection.Close(); diff --git a/Hazel.UnitTests/UdpConnectionTests.cs b/Hazel.UnitTests/UdpConnectionTests.cs index b93e6fb..363fb4d 100644 --- a/Hazel.UnitTests/UdpConnectionTests.cs +++ b/Hazel.UnitTests/UdpConnectionTests.cs @@ -3,6 +3,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Net; using System.Threading; +using Hazel.Udp; + namespace Hazel.UnitTests { [TestClass] @@ -14,13 +16,14 @@ namespace Hazel.UnitTests [TestMethod] public void UdpFieldTest() { + NetworkEndPoint ep = new NetworkEndPoint(IPAddress.Loopback, 4296); + using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(ep)) { listener.Start(); - NetworkEndPoint ep = new NetworkEndPoint(IPAddress.Loopback, 4296); - connection.Connect(ep); + connection.Connect(); //Connection fields Assert.AreEqual(ep, connection.EndPoint); @@ -39,11 +42,11 @@ namespace Hazel.UnitTests public void UdpIPv4ConnectionTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296, IPMode.IPv4)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4))) { listener.Start(); - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)); + connection.Connect(); } } @@ -57,14 +60,14 @@ namespace Hazel.UnitTests { listener.Start(); - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4))) { - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)); + connection.Connect(); } - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4AndIPv6))) { - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4AndIPv6)); + connection.Connect(); } } } @@ -76,7 +79,7 @@ namespace Hazel.UnitTests public void UdpUnreliableServerToClientTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunServerToClientTest(listener, connection, 1, 3, SendOption.None); } @@ -89,7 +92,7 @@ namespace Hazel.UnitTests public void UdpReliableServerToClientTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunServerToClientTest(listener, connection, 3, 3, SendOption.Reliable); } @@ -102,7 +105,7 @@ namespace Hazel.UnitTests public void UdpUnreliableClientToServerTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunClientToServerTest(listener, connection, 1, 3, SendOption.None); } @@ -115,7 +118,7 @@ namespace Hazel.UnitTests public void UdpReliableClientToServerTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunClientToServerTest(listener, connection, 3, 3, SendOption.Reliable); } @@ -128,11 +131,11 @@ namespace Hazel.UnitTests public void KeepAliveClientTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { listener.Start(); - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296)); + connection.Connect(); connection.KeepAliveInterval = 100; System.Threading.Thread.Sleep(1100); //Enough time for ~10 keep alive packets @@ -154,7 +157,7 @@ namespace Hazel.UnitTests ManualResetEvent mutex = new ManualResetEvent(false); using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { listener.NewConnection += delegate(object sender, NewConnectionEventArgs args) { @@ -173,7 +176,7 @@ namespace Hazel.UnitTests listener.Start(); - connection.Connect(new NetworkEndPoint(IPAddress.Loopback, 4296)); + connection.Connect(); mutex.WaitOne(); } @@ -186,7 +189,7 @@ namespace Hazel.UnitTests public void ClientDisconnectTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunClientDisconnectTest(listener, connection); } @@ -199,7 +202,7 @@ namespace Hazel.UnitTests public void ServerDisconnectTest() { using (UdpConnectionListener listener = new UdpConnectionListener(IPAddress.Any, 4296)) - using (UdpConnection connection = new UdpClientConnection()) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { TestHelper.RunServerDisconnectTest(listener, connection); } diff --git a/Hazel/Connection.cs b/Hazel/Connection.cs index 1f67312..c235f7e 100644 --- a/Hazel/Connection.cs +++ b/Hazel/Connection.cs @@ -40,15 +40,15 @@ namespace Hazel /// /// /// DataReceived is invoked everytime a message is received from the end point of this connection, the message - /// that was received can be found in the alongside other information from the + /// that was received can be found in the alongside other information from the /// event. /// /// /// /// - /// + /// /// - public event EventHandler DataReceived; + public event EventHandler DataReceived; /// /// Called when the end point disconnects or an error occurs. @@ -62,7 +62,7 @@ namespace Hazel /// /// /// - /// + /// /// public event EventHandler Disconnected; @@ -163,10 +163,10 @@ namespace Hazel /// /// /// Calling Connect makes the connection attempt to connect to the end point that's specified in the - /// passed. This method will block until the connection attempt completes and - /// will throw a if there is a problem connecting. + /// constructor. This method will block until the connection attempt completes and will throw a + /// if there is a problem connecting. /// - public abstract void Connect(ConnectionEndPoint remoteEndPoint); + public abstract void Connect(); /// /// Invokes the DataReceived event. @@ -180,11 +180,11 @@ namespace Hazel /// protected void InvokeDataReceived(byte[] bytes, SendOption sendOption) { - DataEventArgs args = DataEventArgs.GetObject(); + DataReceivedEventArgs args = DataReceivedEventArgs.GetObject(); args.Set(bytes, sendOption); //Make a copy to avoid race condition between null check and invocation - EventHandler handler = DataReceived; + EventHandler handler = DataReceived; if (handler != null) handler(this, args); } @@ -231,7 +231,7 @@ namespace Hazel /// connection. /// /// - /// This calls and therefore sets straight to + /// This calls and therefore sets straight to /// . Once you call Close you will not be able to send any more /// data using this connection and no more data will be received. /// diff --git a/Hazel/ConnectionListener.cs b/Hazel/ConnectionListener.cs index 8c4e165..4cd01a8 100644 --- a/Hazel/ConnectionListener.cs +++ b/Hazel/ConnectionListener.cs @@ -38,13 +38,13 @@ namespace Hazel /// /// Hazel doesn't store connections so it is your responsibility to keep track of the connections to your /// server. Note that as implements if you are not storing - /// a connection then as a bare minimum you should call here in order to + /// a connection then as a bare minimum you should call here in order to /// release the connection correctly. /// /// /// /// - /// + /// /// public event EventHandler NewConnection; @@ -57,18 +57,18 @@ namespace Hazel /// connects the event will be invoked containing the connection to the new client. /// /// - /// To stop listening you should call . + /// To stop listening you should call . /// /// /// - /// + /// /// public abstract void Start(); /// /// Invokes the NewConnection event with the supplied connection. /// - /// The connection to pass to subscribers. + /// The connection to pass in the arguments. /// /// Implementers should call this to invoke the event before data is received so that /// subscribers do not miss any data that may have been sent immediately after connecting. @@ -85,6 +85,18 @@ namespace Hazel handler(this, args); } + /// + /// Closes the connection listener safely. + /// + /// + /// Internally this simply calls Dispose therefore trying to reuse the ConnectionListener after calling Close will + /// cause ObjectDisposedExceptions. + /// + public virtual void Close() + { + Dispose(); + } + /// /// Call to dispose of the connection listener. /// diff --git a/Hazel/DataEventArgs.cs b/Hazel/DataEventArgs.cs index 1dd3c26..ef86cf9 100644 --- a/Hazel/DataEventArgs.cs +++ b/Hazel/DataEventArgs.cs @@ -6,28 +6,28 @@ using System.Text; namespace Hazel { /// - /// Event arguments for the event. + /// Event arguments for the event. /// /// /// /// This contains information about messages received by a connection and is passed to subscribers of the - /// DataEvent. + /// DataEvent. /// /// /// /// - public class DataEventArgs : EventArgs, IRecyclable + public class DataReceivedEventArgs : EventArgs, IRecyclable { /// /// Object pool for this event. /// - static readonly ObjectPool objectPool = new ObjectPool(() => new DataEventArgs()); + static readonly ObjectPool objectPool = new ObjectPool(() => new DataReceivedEventArgs()); /// /// Returns an instance of this object from the pool. /// /// A new or recycled DataEventArgs object. - internal static DataEventArgs GetObject() + internal static DataReceivedEventArgs GetObject() { return objectPool.GetObject(); } @@ -45,7 +45,7 @@ namespace Hazel /// /// Private constructor for object pool. /// - DataEventArgs() + DataReceivedEventArgs() { } diff --git a/Hazel/DisconnectedEventArgs.cs b/Hazel/DisconnectedEventArgs.cs index 1942244..21e29f5 100644 --- a/Hazel/DisconnectedEventArgs.cs +++ b/Hazel/DisconnectedEventArgs.cs @@ -36,9 +36,10 @@ namespace Hazel /// The exception, if any, that caused the disconnect. /// /// - /// If the disconnection was caused because of an exception occuring (for exemple a - /// on network based connections) this will contain the error that caused it or a - /// with the details of the exception, if the disconnection wasn't caused by an error then this will contain null. + /// If the disconnection was caused because of an exception occuring (for exemple a + /// on network based connections) this will contain the error + /// that caused it or a with the details of the exception, if the disconnection + /// wasn't caused by an error then this will contain null. /// public Exception Exception { get; private set; } diff --git a/Hazel/DocInclude/common.xml b/Hazel/DocInclude/common.xml index 76edc64..5e9ab9e 100644 --- a/Hazel/DocInclude/common.xml +++ b/Hazel/DocInclude/common.xml @@ -3,12 +3,12 @@ - As with all Hazel events it is invoked on a thread from the .NET and hence any - subscribers should ensure their handling code is thread safe. Implementing connections are not bound to - invoking this event in the sequence messages are received, in fact implementers are only required to - ensure this method is always and only invoked for a user sent message, therefore subscribers should be - aware that this event may be called out of order and may be called whilst another thread is still handling - an invocation of the event. + As with all Hazel events it is invoked on a thread from the .NET + ThreadPool and hence any subscribers should ensure their + handling code is thread safe. Implementing connections are not bound to invoking this event in the sequence + messages are received, in fact implementers are only required to ensure this method is always and only invoked + for a user sent message, therefore subscribers should be aware that this event may be called out of order and + may be called whilst another thread is still handling an invocation of the event. @@ -25,7 +25,7 @@ This method sends a number of bytes in a message to the end point of this client using the given to describe how the data should be sent. Sending messages requires that the this connection is connected to a remote end point and SendBytes will throw an exception if that is not - the case. See the property for information on whether a connection is connected or not. + the case. See the property for information on whether a connection is connected or not. \ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Content Layout.content b/Hazel/Documentation/Documentation/Content Layout.content new file mode 100644 index 0000000..e69b068 --- /dev/null +++ b/Hazel/Documentation/Documentation/Content Layout.content @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Introduction.aml b/Hazel/Documentation/Documentation/Introduction.aml new file mode 100644 index 0000000..f7a891e --- /dev/null +++ b/Hazel/Documentation/Documentation/Introduction.aml @@ -0,0 +1,24 @@ + + + + + + + Welcome to the Hazel documentation! Here you will find technical + details, API references and tutorials for getting started with Hazel. + + + Hazel Networking is an open source low level networking library for C# providing + connection orientated, message bassed communication via TCP, UDP and + RUDP. You can download it from Github + + here + https://github.com/DarkRiftNetworking/Hazel-Networking + _blank + + . + + + + + \ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Quickstart.aml b/Hazel/Documentation/Documentation/Quickstart.aml new file mode 100644 index 0000000..6cc3943 --- /dev/null +++ b/Hazel/Documentation/Documentation/Quickstart.aml @@ -0,0 +1,337 @@ + + + + + + + Hazel is a low level networking library that takes away a lot of the pain of writing sockets. Hazel provides the guarantee of connection orientated, message based communication across TCP, UDP and RUDP. + + + This guide will take you through the stages of writing a console based server and connecting to it from a console based client. + + + + + +
+ Creating a Server + + + Creating a Listener + + + + Create a new solution containing a Console project named "Server" (or at least something obvious). + + + + + Add a reference to Hazel.dll in the project. + + + + + Modify the default file to look like this, we'll go through each part individually. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Net; + +using Hazel; +using Hazel.Tcp; + +namespace HazelExample +{ + class ServerExample + { + static ConnectionListener listener; + + public static void Main(string[] args) + { + listener = new TcpConnectionListener(IPAddress.Any, 4296); + + listener.NewConnection += NewConnectionHandler; + + Console.WriteLine("Starting server!"); + + listener.Start(); + + Console.WriteLine("Press any key to continue..."); + + Console.ReadKey(); + + listener.Close(); + } + } +} + + + Firstly we need to tell the compiler that we are using Hazel; and using Hazel.Tcp; so we have access to Hazel's general and TCP specific types. Secondly we create a T:Hazel.ConnectionListener, these wait on a specified port and accept new clients to the server invoking the E:Hazel.ConnectionListener.NewConnection event each time a new client connects. + + + We then instruct the ConnectionListener to begin listening for new clients by calling M:ConnectionListener.Start and then finally we close the listener using M:ConnectionListener.Close. + + + In this circumstance it would be much better if we enclosed the listener within a using block as it implements IDisposable, however for the majority of use cases you are more likely to use the listener in this way. If you want to see it used in a using block then look at the unit tests. + + + If you want to use UDP instead of TCP then it is as simple as including the Hazel.Udp namespace and creating a T:UdpConnectionListener instead. + + + + + + + + Handling Events + + + + In the last example we subscribed to the E:ConnectionListener.NewConnection event but we never spsecified what to do in that event. Add the following method to your code. + +static void NewConnectionHandler(object sender, NewConnectionEventArgs args) +{ + Console.WriteLine("New connection from " + args.Connection.EndPoint.ToString(); + + args.Connection.DataReceived += DataReceivedHandler; +} + + This method is fairly simple, it follows the standard event handler delegate and take a sender (in this case it will be the ConnectionListener that called the event) and some args. The args contain a Connection which is the main object we use for communication with clients. + You can imagine this process in a similar way to TCP. You create a listener which creates sockets on the server side for each client socket that connects to it. + In this method we simply print out the IP of the client that just connected and then we subscribe to any data that this client sends us. You may also want to store the connection here for later reference as Hazel doesn't maintain a list of connection for you. + + + + + Once again we've got an undeclared event handler so lets fill that in now. + +private static void DataReceivedHandler(object sender, DataEventArgs args) +{ + Connection connection = (Connection)sender; + + Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString()); + + connection.SendBytes(args.Bytes, args.SendOption); + + args.Recycle(); +} + + Again this method follows the standard event handler delegate and this time we make use of the sender parameter to get the connection that received the data. We then go on to print out the data received and then we send it back to the client using M:ConnectionListener.SendBytes. When we send we specify that the send option should be the same as the data that was received, we'll talk more about send options later. + You have also probably noticed that I didn't mention the M:DataEventArgs.Recycle call. Recycle is an optional call that tells Hazel that it is now safe to use the object again rather than creating a new one and having to wait for the GC to collect the old object. If you are sending a lot of data then you will get less GC runs if you call Recycle but it is not necerssary to call it and if you dont the GC will collect it as normal. Also note that you should only call Recycle once you are done using the object otherwise the data inside it may change! + + + + + + In total, you should have something like this. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Net; + +using Hazel; +using Hazel.Tcp; + +namespace HazelExample +{ + class ServerExample + { + static ConnectionListener listener; + + public static void Main(string[] args) + { + listener = new TcpConnectionListener(IPAddress.Any, 4296); + + listener.NewConnection += NewConnectionHandler; + + Console.WriteLine("Starting server!"); + + listener.Start(); + + Console.WriteLine("Press any key to continue..."); + + Console.ReadKey(); + + listener.Close(); + } + + static void NewConnectionHandler(object sender, NewConnectionEventArgs args) + { + Console.WriteLine("New connection from " + args.Connection.EndPoint.ToString(); + + args.Connection.DataReceived += DataReceivedHandler; + + args.Recycle(); + } + + private static void DataReceivedHandler(object sender, DataEventArgs args) + { + Connection connection = (Connection)sender; + + Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString()); + + connection.SendBytes(args.Bytes, args.SendOption); + + args.Recycle(); + } + } +} + + +
+ +
+ Creating a Client + + + Connecting to a Server + + + + Create a new project in your solution for th client and add a reference to Hazel.dll. + + + + + + Modify the default file to contain the following. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Hazel; +using Hazel.Tcp; + +namespace HazelExample +{ + class ClientExample + { + static Connection connection; + + public static void Main(string[] args) + { + NetworkEndPoint endPoint = new NetworkEndPoint("127.0.0.1", 4296); + + connection = new TcpConnection(endPoint); + + connection.DataReceived += DataReceived; + + Console.WriteLine("Connecting!"); + + connection.Connect(); + + Console.WriteLine("Press any key to continue..."); + + Console.ReadKey(); + + connection.Close(); + } + } +} + + As you can see you simply create a T:NetworkEndPoint for the remote server and then pass it into a new T:Connection. Then you can setup any events needed and finally call M:Connection.Connect to begin the connection. + Finally we close the connection using M:Connection.Close. Again, Connection implements IDisposable and so must be closed, if it is easier you could wrap it in a using block. + + If you are using UDP instead of TCP then include the Hazel.Udp namespace and create a T:UdpClientConnection instead. + + + + + + + + Handling Events + + + + Add the following event handler to receive data, you'll notice that this is the same event we used in the server and so it will not be explained. + +private static void DataReceived(object sender, DataEventArgs args) +{ + Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString()); + + args.Recycle(); +} + + + + + + + + Sending Messages + + + + Sending a message is the same for both the server and client, you simply call M:Connection.SendBytes on your connection. + Add the following line after the call to Connect + +connection.SendBytes(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + + + + + + You should have something like this. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Hazel; +using Hazel.Tcp; + +namespace HazelExample +{ + class ClientExample + { + static Connection connection; + + public static void Main(string[] args) + { + NetworkEndPoint endPoint = new NetworkEndPoint("127.0.0.1", 4296); + + connection = new TcpConnection(endPoint); + + connection.DataReceived += DataReceived; + + Console.WriteLine("Connecting!"); + + connection.Connect(); + + connection.SendBytes(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + Console.WriteLine("Press any key to continue..."); + + Console.ReadKey(); + + connection.Close(); + } + + private static void DataReceived(object sender, DataEventArgs args) + { + Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString()); + + args.Recycle(); + } + } +} + + +
+
+
\ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Technical Details/Protocols/Protocols.aml b/Hazel/Documentation/Documentation/Technical Details/Protocols/Protocols.aml new file mode 100644 index 0000000..46e03af --- /dev/null +++ b/Hazel/Documentation/Documentation/Technical Details/Protocols/Protocols.aml @@ -0,0 +1,14 @@ + + + + + + + In order to provide the guarantees that it does, Hazel augments each + transport protocol with its own meta data (or header data) that is + hidden from users. + + + + + \ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Technical Details/Protocols/TCP.aml b/Hazel/Documentation/Documentation/Technical Details/Protocols/TCP.aml new file mode 100644 index 0000000..a6259c4 --- /dev/null +++ b/Hazel/Documentation/Documentation/Technical Details/Protocols/TCP.aml @@ -0,0 +1,33 @@ + + + + + + + Hazel's TCP protocol is fairly simple as TCP already provides connection + based communication and thus only needs a message system implementing. + + + +
+ Header Data + + + The TCP protocol is fairly simple interms of header. 4 bytes are + added to mark the number of bytes in each message. + + + + Length (MSB) + Length + Length + Length (LSB) + Data... + +
+ All header data in Hazel is encoded in big endian format. +
+
+ +
+
\ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Technical Details/Protocols/UDP-RUDP.aml b/Hazel/Documentation/Documentation/Technical Details/Protocols/UDP-RUDP.aml new file mode 100644 index 0000000..31dfb62 --- /dev/null +++ b/Hazel/Documentation/Documentation/Technical Details/Protocols/UDP-RUDP.aml @@ -0,0 +1,146 @@ + + + + + + + UDP provides message based communication however it is not connection + oriented nor does it have any built in functionality for reliable or + fragmented delivery of messages hence the implementation to cover this + if fairly complicated. + + + +
+ Header Data + + + The UDP protocol has multiple layers of header data depending on the + send options that are requested with the message. + + + + Unreliable + Type + Data... +   +   + + + Reliable + Type + ID (MSB) + ID (LSB) + Data... + +
+ All header data in Hazel is encoded in big endian format. + + In both of these, Type is an identifier + that holds the SendOption or another value indicating a control + packet of data. The most significant 4 bits of + Type are reserved for future use and the + least significant bits specify the send option flags for the message. + + + + + 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 + + + + Reserved + Reserved + Reserved + Reserved + Control + Reserved + Fragmented + Reliable + +
+ + Reliable and + Fragmented are both flags for their + respective send option, Control, if set, + specifies that the 3 least significant bits refer to a control code: + + + + 0 + Hello + + + 1 + Disconnect + + + 2 + Acknowledgment + +
+
+
+ +
+ Reliable Delivery + + + To implement reliable delivery 2 ID bytes are sent which identify the + packet. When the receiver receives the data is replys with an + acknowledgement packet as follows: + + + + Acknowledgement + Type + ID (MSB) + ID (LSB) + +
+ + Where type is specifying an acknowledgement packet as laid out above. + + + If the sending client does not receive an acknowledgement after a + specific amount of time elapses from the pakcet being sent then it + resends that packet and thetime before the next resend of that packet + is doubled. When the sending client receives the acknowledgement is + should not resend the data again. + + + The receiving client must also ensure that it does not present the + same packet to the user twice but must acknowledge any packets it + receives, even if it has already received that packet, in case an + acknowledgement is lost. + + + After a specific number of resends without acknowledgement a sending + client may mark assume that communication has been interrupted and + thus mark the connection as disconnected. + +
+
+ +
+ Keepalive packets + + + Keepalive packets should be sent after a specific time has elapsed + since the last packet (either keepalive, acknowledgement or user sent) + was transmitted and should be sent using reliable delivery so that an + acknowledgement can be received to indicate communication has not been + lost. As packets that are not acknowledged should cause a + disconnection no additional logic is required for keepalives. + + +
+
+
\ No newline at end of file diff --git a/Hazel/Documentation/Documentation/Technical Details/Technical Details.aml b/Hazel/Documentation/Documentation/Technical Details/Technical Details.aml new file mode 100644 index 0000000..9b4729e --- /dev/null +++ b/Hazel/Documentation/Documentation/Technical Details/Technical Details.aml @@ -0,0 +1,14 @@ + + + + + + + Underneath Hazel there are a lot of technicalities, this section will + help outline those details so you understand Hazel's implementations + better. + + + + + \ No newline at end of file diff --git a/Hazel/Hazel.shfbproj b/Hazel/Documentation/Hazel.shfbproj similarity index 69% rename from Hazel/Hazel.shfbproj rename to Hazel/Documentation/Hazel.shfbproj index cd9f323..f46d602 100644 --- a/Hazel/Hazel.shfbproj +++ b/Hazel/Documentation/Hazel.shfbproj @@ -25,8 +25,8 @@ False True - - + + 1.0.0.0 2 False @@ -38,6 +38,10 @@ Guid Hazel Networking AboveNamespaces + + The Hazel namespace contains various classes used across the different communication methods implemented. +Namespace for classes relating to communication via TCP. +Namespace for classes relating to communication via TCP. @@ -69,7 +73,24 @@ OnBuildSuccess - + + + + + + + + + + + + + + + + + + Hazel {02CFBD30-D77D-400F-94B2-700F60EFDD7F} diff --git a/Hazel/Hazel.csproj b/Hazel/Hazel.csproj index ce4bf63..1bf7a70 100644 --- a/Hazel/Hazel.csproj +++ b/Hazel/Hazel.csproj @@ -70,18 +70,18 @@ - + - - - - + + + + Code - - - - + + + + diff --git a/Hazel/NetworkEndPoint.cs b/Hazel/NetworkEndPoint.cs index aa114a3..7e71171 100644 --- a/Hazel/NetworkEndPoint.cs +++ b/Hazel/NetworkEndPoint.cs @@ -30,7 +30,8 @@ namespace Hazel /// /// Creates a NetworkEndPoint from a given EndPoint. /// - /// The end point to wrap./param> + /// The end point to wrap. + /// The IP mode to use. public NetworkEndPoint(EndPoint endPoint, IPMode mode = IPMode.IPv4AndIPv6) { this.EndPoint = endPoint; @@ -42,6 +43,7 @@ namespace Hazel /// /// The IP address of the server. /// The port the server is listening on. + /// The IP mode to use. /// /// When using this constructor will contain an . /// @@ -56,13 +58,20 @@ namespace Hazel /// /// A valid IP address of the server. /// The port the server is listening on. + /// The IP mode to use. /// /// When using this constructor will contain an . /// public NetworkEndPoint(string IP, int port, IPMode mode = IPMode.IPv4AndIPv6) : this(IPAddress.Parse(IP), port) { + + } + /// + public override string ToString() + { + return EndPoint.ToString(); } } } diff --git a/Hazel/SendOption.cs b/Hazel/SendOption.cs index c45c08e..2629711 100644 --- a/Hazel/SendOption.cs +++ b/Hazel/SendOption.cs @@ -31,7 +31,7 @@ namespace Hazel /// typically requires more processing, more memory (as packets need to be stored in case they need resending), /// a larger number of protocol bytes and can be slower than unreliable delivery. /// - Reliable = 16, + Reliable = 1, /// /// Requests data be sent so that large messages are fragmented into smaller chunks of @@ -42,7 +42,7 @@ namespace Hazel /// that do not support the transmission of large messages. Without specifying reliable delivery there is no /// guarentee that the message will arrive but any incomplete messages will be simply be discarded. /// - Fragmented = 32, + Fragmented = 2, /// /// Requests data be sent so that large messages are fragmented into smaller chunks of @@ -54,6 +54,6 @@ namespace Hazel /// guaranteed to arrive and to arrive only once but the sending process may require more memory, processing, /// a larger number protocol bytes and may be slower than sending unreliably. /// - FragmentedReliable = 48 + FragmentedReliable = 3 } } diff --git a/Hazel/SendOptionInternal.cs b/Hazel/SendOptionInternal.cs index 212467d..e39e7e5 100644 --- a/Hazel/SendOptionInternal.cs +++ b/Hazel/SendOptionInternal.cs @@ -14,16 +14,16 @@ namespace Hazel /// /// Hello message for initiating communication. /// - Hello = 128, + Hello = 8, /// /// Message for discontinuing communication. /// - Disconnect = 129, + Disconnect = 9, /// /// Message acknowledging the receipt of a message. /// - Acknowledgement = 130 + Acknowledgement = 10 } } diff --git a/Hazel/StateObject.cs b/Hazel/Tcp/StateObject.cs similarity index 90% rename from Hazel/StateObject.cs rename to Hazel/Tcp/StateObject.cs index b025b5a..c5878f9 100644 --- a/Hazel/StateObject.cs +++ b/Hazel/Tcp/StateObject.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Hazel +namespace Hazel.Tcp { /// /// Represents the state of the current receive operation for TCP connections. @@ -30,6 +30,7 @@ namespace Hazel /// Creates a StateObject with the specified length. /// /// The number of bytes expected to be received. + /// The callback to invoke once data has been received. internal StateObject(int length, Action callback) { this.buffer = new byte[length]; diff --git a/Hazel/TcpConnection.cs b/Hazel/Tcp/TcpConnection.cs similarity index 95% rename from Hazel/TcpConnection.cs rename to Hazel/Tcp/TcpConnection.cs index db122f4..62e32cb 100644 --- a/Hazel/TcpConnection.cs +++ b/Hazel/Tcp/TcpConnection.cs @@ -5,7 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Text; -namespace Hazel +namespace Hazel.Tcp { /// /// Represents a connection that uses the TCP protocol. @@ -48,47 +48,19 @@ namespace Hazel /// /// Creates a new TCP connection. /// - public TcpConnection() - { - - } - - /// - /// Internal call to start listening once this socket has been constructed and is ready. - /// - internal void StartListening() - { - //Start receiving data - try - { - StartWaitingForHeader(); - } - catch (SocketException e) - { - throw new HazelException("A Socket exception occured while initiating a receive operation.", e); - } - } - - /// /// A to connect to. - public override void Connect(ConnectionEndPoint remoteEndPoint) + public TcpConnection(NetworkEndPoint remoteEndPoint) { - NetworkEndPoint nep = remoteEndPoint as NetworkEndPoint; - if (nep == null) - { - throw new ArgumentException("The remote end point of a TCP connection must be a NetworkEndPoint."); - } - lock (socketLock) { if (State != ConnectionState.NotConnected) throw new InvalidOperationException("Cannot connect as the Connection is already connected."); this.EndPoint = remoteEndPoint; - this.RemoteEndPoint = nep.EndPoint; + this.RemoteEndPoint = remoteEndPoint.EndPoint; //Create a socket - if (nep.IPMode == IPMode.IPv4) + if (remoteEndPoint.IPMode == IPMode.IPv4) socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); else { @@ -99,17 +71,40 @@ namespace Hazel } //Set parameters of socket - if (nep.IPMode == IPMode.IPv4AndIPv6) + if (remoteEndPoint.IPMode == IPMode.IPv4AndIPv6) socket.DualMode = true; socket.NoDelay = true; + } + } + + /// + /// Internal call to start listening once this socket has been constructed and is ready. + /// + internal void StartListening() + { + //Start receiving data + try + { + StartWaitingForHeader(); + } + catch (SocketException e) + { + throw new HazelException("A Socket exception occured while initiating a receive operation.", e); + } + } + /// + public override void Connect() + { + lock(socketLock) + { //Connect State = ConnectionState.Connecting; try { - socket.Connect(nep.EndPoint); + socket.Connect(RemoteEndPoint); } catch (SocketException e) { diff --git a/Hazel/TcpConnectionListener.cs b/Hazel/Tcp/TcpConnectionListener.cs similarity index 98% rename from Hazel/TcpConnectionListener.cs rename to Hazel/Tcp/TcpConnectionListener.cs index 2eaa8b4..055febe 100644 --- a/Hazel/TcpConnectionListener.cs +++ b/Hazel/Tcp/TcpConnectionListener.cs @@ -6,9 +6,7 @@ using System.Net.Sockets; using System.Text; using System.Threading.Tasks; -//TODO replace copyright notices with MIT licenses - -namespace Hazel +namespace Hazel.Tcp { /// /// Listens for new TCP connections and creates TCPConnections for them. diff --git a/Hazel/UdpClientConnection.cs b/Hazel/Udp/UdpClientConnection.cs similarity index 94% rename from Hazel/UdpClientConnection.cs rename to Hazel/Udp/UdpClientConnection.cs index 7052b73..c0df18b 100644 --- a/Hazel/UdpClientConnection.cs +++ b/Hazel/Udp/UdpClientConnection.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace Hazel +namespace Hazel.Udp { /// /// Represents a client's connection to a server that uses the UDP protocol. @@ -33,10 +33,23 @@ namespace Hazel /// /// Creates a new UdpClientConnection. /// - public UdpClientConnection() + /// A to connect to. + public UdpClientConnection(NetworkEndPoint remoteEndPoint) : base() { - + lock (socketLock) + { + this.EndPoint = remoteEndPoint; + this.RemoteEndPoint = remoteEndPoint.EndPoint; + + if (remoteEndPoint.IPMode == IPMode.IPv4) + socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + else + { + socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); + socket.DualMode = true; + } + } } /// @@ -71,28 +84,10 @@ namespace Hazel } /// - /// A to connect to. - public override void Connect(ConnectionEndPoint remoteEndPoint) + public override void Connect() { - NetworkEndPoint nep = remoteEndPoint as NetworkEndPoint; - if (nep == null) + lock(socketLock) { - throw new ArgumentException("The remote end point of a UDP connection must be a NetworkEndPoint."); - } - - lock (socketLock) - { - this.EndPoint = nep; - this.RemoteEndPoint = nep.EndPoint; - - if (nep.IPMode == IPMode.IPv4) - socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - else - { - socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); - socket.DualMode = true; - } - if (State != ConnectionState.NotConnected) throw new InvalidOperationException("Cannot connect as the Connection is already connected."); diff --git a/Hazel/UdpConnection.KeepAlive.cs b/Hazel/Udp/UdpConnection.KeepAlive.cs similarity index 99% rename from Hazel/UdpConnection.KeepAlive.cs rename to Hazel/Udp/UdpConnection.KeepAlive.cs index e9ab122..f2864f7 100644 --- a/Hazel/UdpConnection.KeepAlive.cs +++ b/Hazel/Udp/UdpConnection.KeepAlive.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace Hazel +namespace Hazel.Udp { partial class UdpConnection { diff --git a/Hazel/UdpConnection.Reliable.cs b/Hazel/Udp/UdpConnection.Reliable.cs similarity index 98% rename from Hazel/UdpConnection.Reliable.cs rename to Hazel/Udp/UdpConnection.Reliable.cs index 3c3cf64..2c40fc1 100644 --- a/Hazel/UdpConnection.Reliable.cs +++ b/Hazel/Udp/UdpConnection.Reliable.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace Hazel +namespace Hazel.Udp { partial class UdpConnection { @@ -51,7 +51,7 @@ namespace Hazel /// The maximum times a message should be resent before marking the endpoint as disconnected. /// /// - /// Reliable packets will be resent at an interval defined in for the number of times + /// Reliable packets will be resent at an interval defined in for the number of times /// specified here. Once a packet has been retransmitted this number of times and has not been acknowledged the /// connection will be marked as disconnected and the Disconnected event /// will be invoked. @@ -141,6 +141,7 @@ namespace Hazel /// Writes the bytes neccessary for a reliable send and stores the send. /// /// The byte array to write to. + /// The callback to make once the packet has been acknowledged. void WriteReliableSendHeader(byte[] bytes, Action ackCallback) { lock (reliableDataPacketsSent) diff --git a/Hazel/UdpConnection.cs b/Hazel/Udp/UdpConnection.cs similarity index 99% rename from Hazel/UdpConnection.cs rename to Hazel/Udp/UdpConnection.cs index 8890c92..98afd27 100644 --- a/Hazel/UdpConnection.cs +++ b/Hazel/Udp/UdpConnection.cs @@ -6,7 +6,7 @@ using System.Net.Sockets; using System.Text; using System.Threading; -namespace Hazel +namespace Hazel.Udp { /// /// Represents a connection that uses the UDP protocol. diff --git a/Hazel/UdpConnectionListener.cs b/Hazel/Udp/UdpConnectionListener.cs similarity index 99% rename from Hazel/UdpConnectionListener.cs rename to Hazel/Udp/UdpConnectionListener.cs index 0572b61..4d10dcc 100644 --- a/Hazel/UdpConnectionListener.cs +++ b/Hazel/Udp/UdpConnectionListener.cs @@ -6,7 +6,7 @@ using System.Net.Sockets; using System.Text; using System.Threading.Tasks; -namespace Hazel +namespace Hazel.Udp { /// /// Listens for new UDP connections and creates UdpConnections for them. diff --git a/Hazel/UdpServerConnection.cs b/Hazel/Udp/UdpServerConnection.cs similarity index 92% rename from Hazel/UdpServerConnection.cs rename to Hazel/Udp/UdpServerConnection.cs index 7940913..eca3c3e 100644 --- a/Hazel/UdpServerConnection.cs +++ b/Hazel/Udp/UdpServerConnection.cs @@ -5,7 +5,7 @@ using System.Net; using System.Text; using System.Threading.Tasks; -namespace Hazel +namespace Hazel.Udp { /// /// Represents a servers's connection to a client that uses the UDP protocol. @@ -56,11 +56,11 @@ namespace Hazel /// /// - /// This will always throw an InvalidOperationException. + /// This will always throw a HazelException. /// - public override void Connect(ConnectionEndPoint remoteEndPoint) + public override void Connect() { - throw new InvalidOperationException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?"); + throw new HazelException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?"); } /// -- 2.39.5