├── .gitignore
├── Demos
└── Messenger
│ ├── Messenger.csproj
│ └── Program.cs
├── Implementation
├── ObjectTransport.Serializer.JSON
│ ├── JSONserializer.cs
│ ├── ObjectTransport.JSON.csproj
│ └── ObjectTransportAssemblyLine_JSONExtension.cs
├── ObjectTransport.Serializer.protobuf
│ ├── ObjectTransport.Protobuf.csproj
│ ├── ObjectTransportAssemblyLine_protobufExtension.cs
│ └── ProtobufSerializer.cs
├── ObjectTransport.TCP
│ ├── ObjectTransport.TCP.csproj
│ ├── ObjectTransportFactoryTCPExtension.cs
│ ├── TCPClientChannel.cs
│ ├── TCPMessage.cs
│ ├── TCPServerChannel.cs
│ └── TCPUtilities.cs
└── ObjectTransport.UDP
│ ├── ObjectTransport.UDP.csproj
│ ├── ObjectTransportFactoryUDPExtension.cs
│ ├── UDPClientChannel.cs
│ └── UDPServerChannel.cs
├── LICENSE
├── LICENSE.LiteNetLib.txt
├── ObjectTransport.sln
├── ObjectTransport.tests
├── NetworkChannel.tests
│ ├── INetworkChannelGenericTests.cs
│ ├── TCPNetworkChannelGenericTests.cs
│ ├── UDPNetworkChannelGenericTests.cs
│ └── Utilities
│ │ └── TCPNetworkChannelFactory.cs
├── ObjectTransport.Test.csproj
├── ObjectTransport_OnConnect.tests.cs
├── ObjectTransport_Receive.tests.cs
├── ObjectTransport_Send.tests.cs
├── ObjectTransport_TimeOut.tests.cs
├── Serializer
│ ├── Protobuf_MockObjectMessage.cs
│ └── Protobuf_Serializer.tests.cs
└── Utilities
│ ├── MockNetworkChannelFactory.cs
│ ├── MockObjectMessage.cs
│ ├── MockObjectMessageWithBinary.cs
│ ├── TestObjectTransportFactory.cs
│ └── Utilities.cs
├── ObjectTransport
├── Client.cs
├── Factory
│ ├── ObjectTransportAssemblyLine.cs
│ └── ObjectTransportFactory.cs
├── IObjectTransport.cs
├── MessageReceive.cs
├── MessageResponseHandle.cs
├── MessageSend.cs
├── Network Channels
│ └── INetworkChannel.cs
├── ObjectTransport.cs
├── ObjectTransport.csproj
├── ObjectTransportException.cs
├── PayLoad
│ ├── QueuedMessage.cs
│ ├── ReceivedConnection.cs
│ └── ReceivedMessage.cs
├── ReceivedMessageHandle.cs
└── Serializer
│ └── ISerializer.cs
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # Benchmark Results
46 | BenchmarkDotNet.Artifacts/
47 |
48 | # .NET Core
49 | project.lock.json
50 | project.fragment.lock.json
51 | artifacts/
52 | **/Properties/launchSettings.json
53 |
54 | *_i.c
55 | *_p.c
56 | *_i.h
57 | *.ilk
58 | *.meta
59 | *.obj
60 | *.pch
61 | *.pdb
62 | *.pgc
63 | *.pgd
64 | *.rsp
65 | *.sbr
66 | *.tlb
67 | *.tli
68 | *.tlh
69 | *.tmp
70 | *.tmp_proj
71 | *.log
72 | *.vspscc
73 | *.vssscc
74 | .builds
75 | *.pidb
76 | *.svclog
77 | *.scc
78 |
79 | # Chutzpah Test files
80 | _Chutzpah*
81 |
82 | # Visual C++ cache files
83 | ipch/
84 | *.aps
85 | *.ncb
86 | *.opendb
87 | *.opensdf
88 | *.sdf
89 | *.cachefile
90 | *.VC.db
91 | *.VC.VC.opendb
92 |
93 | # Visual Studio profiler
94 | *.psess
95 | *.vsp
96 | *.vspx
97 | *.sap
98 |
99 | # TFS 2012 Local Workspace
100 | $tf/
101 |
102 | # Guidance Automation Toolkit
103 | *.gpState
104 |
105 | # ReSharper is a .NET coding add-in
106 | _ReSharper*/
107 | *.[Rr]e[Ss]harper
108 | *.DotSettings.user
109 |
110 | # JustCode is a .NET coding add-in
111 | .JustCode
112 |
113 | # TeamCity is a build add-in
114 | _TeamCity*
115 |
116 | # DotCover is a Code Coverage Tool
117 | *.dotCover
118 |
119 | # Visual Studio code coverage results
120 | *.coverage
121 | *.coveragexml
122 |
123 | # NCrunch
124 | _NCrunch_*
125 | .*crunch*.local.xml
126 | nCrunchTemp_*
127 |
128 | # MightyMoose
129 | *.mm.*
130 | AutoTest.Net/
131 |
132 | # Web workbench (sass)
133 | .sass-cache/
134 |
135 | # Installshield output folder
136 | [Ee]xpress/
137 |
138 | # DocProject is a documentation generator add-in
139 | DocProject/buildhelp/
140 | DocProject/Help/*.HxT
141 | DocProject/Help/*.HxC
142 | DocProject/Help/*.hhc
143 | DocProject/Help/*.hhk
144 | DocProject/Help/*.hhp
145 | DocProject/Help/Html2
146 | DocProject/Help/html
147 |
148 | # Click-Once directory
149 | publish/
150 |
151 | # Publish Web Output
152 | *.[Pp]ublish.xml
153 | *.azurePubxml
154 | # Note: Comment the next line if you want to checkin your web deploy settings,
155 | # but database connection strings (with potential passwords) will be unencrypted
156 | *.pubxml
157 | *.publishproj
158 |
159 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
160 | # checkin your Azure Web App publish settings, but sensitive information contained
161 | # in these scripts will be unencrypted
162 | PublishScripts/
163 |
164 | # NuGet Packages
165 | *.nupkg
166 | # The packages folder can be ignored because of Package Restore
167 | **/packages/*
168 | # except build/, which is used as an MSBuild target.
169 | !**/packages/build/
170 | # Uncomment if necessary however generally it will be regenerated when needed
171 | #!**/packages/repositories.config
172 | # NuGet v3's project.json files produces more ignorable files
173 | *.nuget.props
174 | *.nuget.targets
175 |
176 | # Microsoft Azure Build Output
177 | csx/
178 | *.build.csdef
179 |
180 | # Microsoft Azure Emulator
181 | ecf/
182 | rcf/
183 |
184 | # Windows Store app package directories and files
185 | AppPackages/
186 | BundleArtifacts/
187 | Package.StoreAssociation.xml
188 | _pkginfo.txt
189 | *.appx
190 |
191 | # Visual Studio cache files
192 | # files ending in .cache can be ignored
193 | *.[Cc]ache
194 | # but keep track of directories ending in .cache
195 | !*.[Cc]ache/
196 |
197 | # Others
198 | ClientBin/
199 | ~$*
200 | *~
201 | *.dbmdl
202 | *.dbproj.schemaview
203 | *.jfm
204 | *.pfx
205 | *.publishsettings
206 | orleans.codegen.cs
207 |
208 | # Since there are multiple workflows, uncomment next line to ignore bower_components
209 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
210 | #bower_components/
211 |
212 | # RIA/Silverlight projects
213 | Generated_Code/
214 |
215 | # Backup & report files from converting an old project file
216 | # to a newer Visual Studio version. Backup files are not needed,
217 | # because we have git ;-)
218 | _UpgradeReport_Files/
219 | Backup*/
220 | UpgradeLog*.XML
221 | UpgradeLog*.htm
222 |
223 | # SQL Server files
224 | *.mdf
225 | *.ldf
226 | *.ndf
227 |
228 | # Business Intelligence projects
229 | *.rdl.data
230 | *.bim.layout
231 | *.bim_*.settings
232 |
233 | # Microsoft Fakes
234 | FakesAssemblies/
235 |
236 | # GhostDoc plugin setting file
237 | *.GhostDoc.xml
238 |
239 | # Node.js Tools for Visual Studio
240 | .ntvs_analysis.dat
241 | node_modules/
242 |
243 | # Typescript v1 declaration files
244 | typings/
245 |
246 | # Visual Studio 6 build log
247 | *.plg
248 |
249 | # Visual Studio 6 workspace options file
250 | *.opt
251 |
252 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
253 | *.vbw
254 |
255 | # Visual Studio LightSwitch build output
256 | **/*.HTMLClient/GeneratedArtifacts
257 | **/*.DesktopClient/GeneratedArtifacts
258 | **/*.DesktopClient/ModelManifest.xml
259 | **/*.Server/GeneratedArtifacts
260 | **/*.Server/ModelManifest.xml
261 | _Pvt_Extensions
262 |
263 | # Paket dependency manager
264 | .paket/paket.exe
265 | paket-files/
266 |
267 | # FAKE - F# Make
268 | .fake/
269 |
270 | # JetBrains Rider
271 | .idea/
272 | *.sln.iml
273 |
274 | # CodeRush
275 | .cr/
276 |
277 | # Python Tools for Visual Studio (PTVS)
278 | __pycache__/
279 | *.pyc
280 |
281 | # Cake - Uncomment if you are using it
282 | # tools/**
283 | # !tools/packages.config
284 |
285 | # Tabs Studio
286 | *.tss
287 |
288 | # Telerik's JustMock configuration file
289 | *.jmconfig
290 |
291 | # BizTalk build output
292 | *.btp.cs
293 | *.btm.cs
294 | *.odx.cs
295 | *.xsd.cs
--------------------------------------------------------------------------------
/Demos/Messenger/Messenger.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp1.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Demos/Messenger/Program.cs:
--------------------------------------------------------------------------------
1 | using OTransport.NetworkChannel.TCP;
2 | using OTransport;
3 | using System;
4 | using OTransport.NetworkChannel.UDP;
5 | using OTransport.Serializer.JSON;
6 |
7 | namespace Messenger
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | Console.WriteLine("Welcome to this simple Chat room!");
14 | Console.WriteLine("Would you like to:");
15 | Console.WriteLine("1) Create a TCP server");
16 | Console.WriteLine("2) Connect to TCP server");
17 |
18 | IObjectTransport transport;
19 |
20 | string answer = Console.ReadLine();
21 |
22 | //Create Server
23 | if (answer == "1")
24 | {
25 | transport = ObjectTransport.Factory.CreateTCPServer()
26 | .UseJSONserialization()
27 | .Build()
28 | .Start("127.0.0.1", 1234);
29 |
30 | //Receive a receive an object of type Message. c= Client, m = Object that was received
31 | transport.Receive((c, m) =>
32 | {
33 | Console.WriteLine("{0} - {1}", c.IPAddress, m.Body);
34 |
35 | //We want all clients to see the message that was sent to the server.
36 | //However, we do not want the original client to receive the message.
37 | transport.Send(m)
38 | .ToAllExcept(c)
39 | .Execute();
40 |
41 | })
42 | .Execute();
43 | }
44 | else
45 | {
46 | //Create Client
47 | transport = ObjectTransport.Factory.CreateTCPClient()
48 | .UseJSONserialization()
49 | .Build()
50 | .Start("127.0.0.1", 1234);
51 |
52 |
53 | transport.Receive((c, m) =>
54 | {
55 | Console.WriteLine("{0} - {1}", c.IPAddress, m.Body);
56 | }
57 | )
58 | .Execute();
59 | }
60 |
61 | //Write to console when a client connects
62 | transport.OnClientConnect(c => Console.WriteLine("{0} - Client connected", c.IPAddress));
63 |
64 | //Write to console when a client disconnects
65 | transport.OnClientDisconnect(c => Console.WriteLine("{0} - Client disconnected", c.IPAddress));
66 |
67 |
68 | Console.WriteLine("Begin Chatting!");
69 |
70 | string message;
71 | while (true)
72 | {
73 | message = Console.ReadLine();
74 |
75 | if (message == "exit")
76 | break;
77 |
78 | transport.Send(new Message() { Body = message })
79 | .ToAll()
80 | .Execute();
81 | }
82 | }
83 | }
84 | public class Message
85 | {
86 | public string Body { get; set; }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.Serializer.JSON/JSONserializer.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using OTransport.Serializer;
3 | using System;
4 |
5 | namespace OTransport.Serializer.JSON
6 | {
7 | public class JSONserializer : ISerializer
8 | {
9 |
10 | public object Deserialize(string objectPayload, Type objectType)
11 | {
12 | return JsonConvert.DeserializeObject(objectPayload,objectType);
13 | }
14 |
15 | public string Serialize(object obj)
16 | {
17 | return JsonConvert.SerializeObject(obj);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.Serializer.JSON/ObjectTransport.JSON.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.6;netcoreapp1.1;net46
5 | OT.Serializer.JSON
6 | OTransport.Serializer.JSON
7 | ObjectTransport.JSON
8 | 0.2.1
9 | Rhyno van der Sluijs
10 | This package contains the JSON serialization implementation for the ObjectTransport framework.
11 | Please see the following link for more information about installing ObjectTransport:
12 | https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
13 |
14 | false
15 |
16 | Update to Nuget package description.
17 |
18 |
19 | https://github.com/RhynoVDS/ObjectTransport
20 | TCP Server Object networking UDP
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.Serializer.JSON/ObjectTransportAssemblyLine_JSONExtension.cs:
--------------------------------------------------------------------------------
1 | using OTransport.Serializer.JSON;
2 | using OTransport.Factory;
3 |
4 | namespace OTransport.Serializer.JSON
5 | {
6 | public static class ObjectTransportAssemblyLine_JSONExtension
7 | {
8 | ///
9 | /// Use Json serialization to serialize objects
10 | ///
11 | ///
12 | public static ObjectTransportAssemblyLine UseJSONserialization(this ObjectTransportAssemblyLine objectTranposrtAssemblyLine)
13 | {
14 | var jsonSerialization = new JSONserializer();
15 | objectTranposrtAssemblyLine.SetSerializer(jsonSerialization);
16 |
17 | return objectTranposrtAssemblyLine;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.Serializer.protobuf/ObjectTransport.Protobuf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.6;netcoreapp1.1;net46
5 | OTransport.Serializer.protobuf
6 | ObjectTransport.Protobuf
7 | 0.2.1
8 | Rhyno van der Sluijs
9 | This package contains the Protobuf serialization implementation for the ObjectTransport framework.
10 | Please see the following link for more information about installing ObjectTransport:
11 | https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
12 |
13 | false
14 |
15 | Update to Nuget package description.
16 |
17 |
18 | https://github.com/RhynoVDS/ObjectTransport
19 | TCP Server Object networking UDP
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.Serializer.protobuf/ObjectTransportAssemblyLine_protobufExtension.cs:
--------------------------------------------------------------------------------
1 | using OTransport.Factory;
2 | using OTransport.Serializer.protobuf;
3 |
4 | namespace OTransport.Serializer.protobuf
5 | {
6 | public static class ObjectTransportAssemblyLine_protobufExtension
7 | {
8 | ///
9 | /// Use Protobuf Serialization to serialize objects
10 | ///
11 | ///
12 | public static ObjectTransportAssemblyLine UseProtobufSerialization(this ObjectTransportAssemblyLine objectTranposrtAssemblyLine)
13 | {
14 | var protobufSerialization = new ProtobufSerializer();
15 | objectTranposrtAssemblyLine.SetSerializer(protobufSerialization);
16 |
17 | return objectTranposrtAssemblyLine;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.Serializer.protobuf/ProtobufSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 |
5 | namespace OTransport.Serializer.protobuf
6 | {
7 | public class ProtobufSerializer : ISerializer
8 | {
9 | public object Deserialize(string objectPayload, Type objectType)
10 | {
11 | byte[] byteArray = Encoding.UTF8.GetBytes(objectPayload);
12 | //byte[] byteArray = Encoding.ASCII.GetBytes(contents);
13 | MemoryStream stream = new MemoryStream(byteArray);
14 | return ProtoBuf.Serializer.Deserialize(objectType, stream);
15 | }
16 |
17 | public string Serialize(object obj)
18 | {
19 | using (MemoryStream stream = new MemoryStream())
20 | {
21 | ProtoBuf.Serializer.Serialize(stream, obj);
22 | return System.Text.Encoding.UTF8.GetString(stream.ToArray());
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.TCP/ObjectTransport.TCP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.6;netcoreapp1.1;net46
5 | ObjectTransport.TCP
6 | PackageReference
7 | true
8 | OTransport.NetworkChannel.TCP
9 | ObjectTransport.TCP
10 | 0.2.4
11 | Rhyno van der Sluijs
12 | This package contains the TCP network channel implementation for the ObjectTransport framework. This package allows you to send and receive objects over TCP.
13 | Please see the following link for more information about installing ObjectTransport:
14 | https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
15 |
16 | false
17 |
18 | This release introduces the DisconnectClient function which allows you to disconnect a connected client.
19 |
20 |
21 | https://github.com/RhynoVDS/ObjectTransport
22 | TCP Server Object networking UDP
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 4.0.0
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.TCP/ObjectTransportFactoryTCPExtension.cs:
--------------------------------------------------------------------------------
1 | using OTransport.Factory;
2 |
3 | namespace OTransport.NetworkChannel.TCP
4 | {
5 | public static class ObjectTransportFactoryTCPExtension
6 | {
7 | ///
8 | /// Create a TCP server. This network channel only supports reliable communication.
9 | ///
10 | /// the IP address to start the server on
11 | /// the port to listen on
12 | ///
13 | public static ObjectTransportAssemblyLine CreateTCPServer(this ObjectTransportFactory o)
14 | {
15 | TCPServerChannel server = new TCPServerChannel();
16 | var assemblyLine = new ObjectTransportAssemblyLine();
17 | assemblyLine.SetNetworkChannel(server);
18 | assemblyLine.SetReliableTransport();
19 |
20 | return assemblyLine;
21 | }
22 |
23 | ///
24 | /// Create a TCP client. This network channel only supports reliable communication.
25 | ///
26 | /// the IP address to start the server on
27 | /// the port to listen on
28 | ///
29 | public static ObjectTransportAssemblyLine CreateTCPClient(this ObjectTransportFactory o)
30 | {
31 | TCPClientChannel client = new TCPClientChannel();
32 |
33 | var assemblyLine = new ObjectTransportAssemblyLine();
34 | assemblyLine.SetNetworkChannel(client);
35 | assemblyLine.SetReliableTransport();
36 |
37 | return assemblyLine;
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.TCP/TCPClientChannel.cs:
--------------------------------------------------------------------------------
1 | using OTransport;
2 | using OTransport.NetworkChannel.TCP;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 |
11 | namespace OTransport.NetworkChannel.TCP
12 | {
13 | public class TCPClientChannel : INetworkChannel
14 | {
15 | private IPAddress IPAddress;
16 | private int EndPointPort;
17 | private int _LocalPort;
18 | private TcpClient tcpClient = null;
19 | private Client client = null;
20 |
21 | private Action onReceiveCallback = null;
22 | private Task ListenTask = null;
23 | Action onConnectCallBack = null;
24 | Action onDisconnectCallBack = null;
25 |
26 | public int LocalPort { get { return _LocalPort; } }
27 |
28 | private void ListenThread()
29 | {
30 | Task clientTask = new Task((c) =>
31 | {
32 | while (true)
33 | {
34 | Byte[] bytes;
35 | try
36 | {
37 | if (!TCPUtilities.IsConnected(tcpClient))
38 | throw new Exception("Client Disconnected");
39 |
40 | NetworkStream ns = tcpClient.GetStream();
41 | if (tcpClient.ReceiveBufferSize > 0)
42 | {
43 | bytes = new byte[tcpClient.ReceiveBufferSize];
44 | ns.Read(bytes, 0, tcpClient.ReceiveBufferSize);
45 | string msg = Encoding.ASCII.GetString(bytes);
46 |
47 | ReceivedMessage message = new ReceivedMessage((Client)c, msg);
48 |
49 | if (onReceiveCallback != null)
50 | onReceiveCallback.Invoke(message);
51 | }
52 | }
53 | catch
54 | {
55 | if (onDisconnectCallBack != null)
56 | onDisconnectCallBack.Invoke((Client)c);
57 |
58 | break;
59 | }
60 |
61 | }
62 | }, client);
63 | clientTask.Start();
64 | ListenTask = clientTask;
65 | }
66 |
67 | private void ConnectToServer()
68 | {
69 | tcpClient.ConnectAsync(IPAddress, EndPointPort).Wait();
70 | }
71 | public void OnClientConnect(Action callBack)
72 | {
73 | onConnectCallBack = callBack;
74 | if (client != null)
75 | onConnectCallBack.Invoke(client);
76 | }
77 |
78 | public void OnReceive(Action callBack)
79 | {
80 | onReceiveCallback = callBack;
81 | }
82 |
83 | public void SendReliable(Client client, string message)
84 | {
85 | }
86 |
87 | public void Stop()
88 | {
89 | if (tcpClient !=null && tcpClient.Connected)
90 | {
91 | tcpClient.Client.Shutdown(SocketShutdown.Both);
92 | tcpClient.Client.Dispose();
93 | }
94 | }
95 |
96 | public void OnClientDisconnect(Action callBack)
97 | {
98 | onDisconnectCallBack = callBack;
99 | }
100 |
101 | public void SetReliable()
102 | {
103 | }
104 |
105 | public void SetUnreliable()
106 | {
107 | throw new NotSupportedException("This network channel does not support un-reliable sending");
108 | }
109 |
110 | public void Send(Client client, string payload)
111 | {
112 | Byte[] data = System.Text.Encoding.ASCII.GetBytes(payload);
113 |
114 | NetworkStream stream = tcpClient.GetStream();
115 |
116 | stream.Write(data, 0, data.Length);
117 | }
118 |
119 | public void DisconnectClient(params Client[] clients)
120 | {
121 | //This is the client, we just stop the client.
122 | Stop();
123 | }
124 |
125 | public void Start(string ipAddress, int endpointPort)
126 | {
127 | tcpClient = new TcpClient();
128 | client = new Client(ipAddress, endpointPort);
129 | IPAddress = IPAddress.Parse(ipAddress);
130 | EndPointPort = endpointPort;
131 |
132 | ConnectToServer();
133 | _LocalPort = ((IPEndPoint)tcpClient.Client.LocalEndPoint).Port;
134 | ListenThread();
135 |
136 | if (client != null)
137 | onConnectCallBack?.Invoke(client);
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.TCP/TCPMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport.NetworkChannel.TCP
6 | {
7 | public class TCPMessage
8 | {
9 | public const string KeepAlive = "";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.TCP/TCPServerChannel.cs:
--------------------------------------------------------------------------------
1 | using OTransport;
2 | using OTransport.NetworkChannel.TCP;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Net.Sockets;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace OTransport.NetworkChannel.TCP
13 | {
14 | public class TCPServerChannel : INetworkChannel
15 | {
16 | private Dictionary ClientToTCPMap = new Dictionary();
17 | private IPAddress IPAddress;
18 | private TcpListener Server;
19 | private int _LocalPort;
20 |
21 | Action onReceiveCallback = null;
22 | List clientTasks = new List();
23 | Action onConnectCallBack = null;
24 | Action onDisconnectCallBack = null;
25 |
26 | public int LocalPort { get { return _LocalPort; } }
27 |
28 | public void Stop()
29 | {
30 | var clients = ClientToTCPMap.Keys.ToArray();
31 | foreach(var client in clients)
32 | {
33 | ClientToTCPMap[client].Client.Shutdown(SocketShutdown.Both);
34 | ClientToTCPMap[client].Client.Dispose();
35 | ClientToTCPMap.Remove(client);
36 | }
37 | Server?.Stop();
38 | }
39 | private void StartListeningThread()
40 | {
41 | Thread listenConnection = new Thread(async() =>
42 | {
43 | while (true)
44 | {
45 | TcpClient tcpClient = null;
46 | try
47 | {
48 | tcpClient = await Server.AcceptTcpClientAsync();
49 | }
50 | catch (ObjectDisposedException) { break; }
51 |
52 | string[] addressArray = tcpClient.Client.RemoteEndPoint.ToString().Split(':');
53 | Client client = new Client(addressArray[0], int.Parse(addressArray[1]));
54 | ClientToTCPMap.Add(client, tcpClient);
55 |
56 | if(onConnectCallBack !=null)
57 | onConnectCallBack.Invoke(client);
58 |
59 |
60 | Task clientTask = new Task(async (c) =>
61 | {
62 | Byte[] bytes;
63 | while (true)
64 | {
65 | try
66 | {
67 | if(!TCPUtilities.IsConnected(tcpClient))
68 | throw new Exception("Client Disconnected");
69 |
70 | NetworkStream ns = tcpClient.GetStream();
71 |
72 | if (tcpClient.ReceiveBufferSize > 0)
73 | {
74 | string receivedMessage = string.Empty;
75 |
76 | do
77 | {
78 | bytes = new byte[tcpClient.ReceiveBufferSize];
79 | ns.Read(bytes, 0, tcpClient.ReceiveBufferSize);
80 | string msg = Encoding.ASCII.GetString(bytes);
81 | receivedMessage += msg;
82 | await Task.Delay(1);
83 | }
84 | while (ns.DataAvailable);
85 |
86 | ReceivedMessage message = null;
87 | message = new ReceivedMessage((Client)c, receivedMessage);
88 |
89 |
90 | if (onReceiveCallback != null)
91 | onReceiveCallback.Invoke(message);
92 | }
93 | }
94 | catch
95 | {
96 | ClientToTCPMap.Remove((Client)c);
97 | if (onDisconnectCallBack != null)
98 | onDisconnectCallBack.Invoke((Client)c);
99 | break;
100 | }
101 |
102 | }
103 | },client);
104 | clientTask.Start();
105 | clientTasks.Add(clientTask);
106 | }
107 | });
108 | listenConnection.Start();
109 | }
110 |
111 | public void OnClientConnect(Action callBack)
112 | {
113 | onConnectCallBack = callBack;
114 | }
115 |
116 | public void OnReceive(Action callBack)
117 | {
118 | onReceiveCallback = callBack;
119 | }
120 |
121 | public void OnClientDisconnect(Action callBack)
122 | {
123 | onDisconnectCallBack = callBack;
124 | }
125 |
126 | public void SetReliable()
127 | {
128 | }
129 |
130 | public void SetUnreliable()
131 | {
132 | throw new NotSupportedException("This network channel does not support un-reliable sending");
133 | }
134 |
135 | public void Send(Client client, string payload)
136 | {
137 | var tcpClient = ClientToTCPMap[client];
138 | Byte[] data = System.Text.Encoding.ASCII.GetBytes(payload);
139 |
140 | NetworkStream stream = tcpClient.GetStream();
141 |
142 | stream.Write(data, 0, data.Length);
143 | }
144 |
145 | public void DisconnectClient(params Client[] clients)
146 | {
147 | foreach(var client in clients)
148 | {
149 | TcpClient tcpclient = ClientToTCPMap[client];
150 | tcpclient.Dispose();
151 | ClientToTCPMap.Remove(client);
152 | }
153 | }
154 |
155 | public void Start(string ipaddress, int port)
156 | {
157 | IPAddress = IPAddress.Parse(ipaddress);
158 |
159 | Server = new TcpListener(IPAddress, port);
160 | Server.Start();
161 | _LocalPort = int.Parse(Server.LocalEndpoint.ToString().Split(':')[1]);
162 |
163 | StartListeningThread();
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.TCP/TCPUtilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net.Sockets;
4 | using System.Text;
5 |
6 | namespace OTransport.NetworkChannel.TCP
7 | {
8 | class TCPUtilities
9 | {
10 | public static bool IsConnected(TcpClient tcpClient)
11 | {
12 | try
13 | {
14 | if (tcpClient != null && tcpClient.Client != null && tcpClient.Client.Connected)
15 | {
16 |
17 | // Detect if client disconnected
18 | if (tcpClient.Client.Poll(0, SelectMode.SelectRead))
19 | {
20 | byte[] buff = new byte[1];
21 | if (tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
22 | {
23 | // Client disconnected
24 | return false;
25 | }
26 | else
27 | {
28 | return true;
29 | }
30 | }
31 |
32 | return true;
33 | }
34 | else
35 | {
36 | return false;
37 | }
38 | }
39 | catch
40 | {
41 | return false;
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.UDP/ObjectTransport.UDP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.6;netcoreapp1.1;net46
5 | ObjectTransport.UDP
6 | OTransport.NetworkChannel.UDP
7 | ObjectTransport.UDP
8 | 0.2.3
9 | Rhyno van der Sluijs
10 | This package contains the UDP network channel implementation for the ObjectTransport framework. This package allows you to send and receive objects over UDP.
11 | Please see the following link for more information about installing ObjectTransport:
12 | https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
13 |
14 | false
15 |
16 | This release introduces the DisconnectClient function which allows you to disconnect a connected client.
17 |
18 |
19 | TCP Server Object networking UDP
20 | https://github.com/RhynoVDS/ObjectTransport
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.UDP/ObjectTransportFactoryUDPExtension.cs:
--------------------------------------------------------------------------------
1 | using OTransport;
2 | using OTransport.Factory;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 |
7 | namespace OTransport.NetworkChannel.UDP
8 | {
9 | public static class ObjectTransportFactoryUDPExtension
10 | {
11 | ///
12 | /// Create a UDP server. This supports reliable and unreliable communications. Defaults to unreliable.
13 | ///
14 | /// the IP address to start the server on
15 | /// the port to listen on
16 | ///
17 | public static ObjectTransportAssemblyLine CreateUDPServer(this ObjectTransportFactory o)
18 | {
19 | UDPServerChannel server = new UDPServerChannel();
20 | var assemblyLine = new ObjectTransportAssemblyLine();
21 | assemblyLine.SetNetworkChannel(server);
22 | assemblyLine.SetUnreliableTransport();
23 |
24 | return assemblyLine;
25 | }
26 |
27 | ///
28 | /// Create a UDP client. This supports reliable and unreliable communications. Defaults to unreliable.
29 | ///
30 | /// the IP address to start the server on
31 | /// the port to listen on
32 | ///
33 | public static ObjectTransportAssemblyLine CreateUDPClient(this ObjectTransportFactory o)
34 | {
35 | var client = new UDPClientChannel();
36 | var assemblyLine = new ObjectTransportAssemblyLine();
37 | assemblyLine.SetNetworkChannel(client);
38 | assemblyLine.SetUnreliableTransport();
39 |
40 | return assemblyLine;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.UDP/UDPClientChannel.cs:
--------------------------------------------------------------------------------
1 | using LiteNetLib;
2 | using LiteNetLib.Utils;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Net.Sockets;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace OTransport.NetworkChannel.UDP
13 | {
14 | public class UDPClientChannel : INetworkChannel
15 | {
16 | //This should technically only ever have on entry as this is the client.
17 | private Dictionary ClientToNetPeerMap = new Dictionary();
18 | private IPAddress IPAddress;
19 |
20 | private EventBasedNetListener listener;
21 | private NetManager clientUDP;
22 |
23 | private int _LocalPort;
24 | private bool ReliableTransport = false;
25 |
26 |
27 | Action onReceiveCallback = null;
28 | Action onConnectCallBack = null;
29 | Action onDisconnectCallBack = null;
30 |
31 | public int LocalPort { get { return _LocalPort; } }
32 |
33 | public void Stop()
34 | {
35 | if(clientUDP?.IsRunning != null && clientUDP?.IsRunning == true)
36 | clientUDP?.Stop();
37 |
38 | foreach (Client client in ClientToNetPeerMap.Keys)
39 | {
40 | onDisconnectCallBack?.Invoke(client);
41 | }
42 | }
43 | private void WaitTillConnectionMade()
44 | {
45 |
46 | int count = 0;
47 |
48 | //Wait until the connection is made and make sure that it doesn't time out.
49 | while(ClientToNetPeerMap.Count() ==0 && count < 1000000000)
50 | {
51 | count += 1;
52 | }
53 | }
54 | private Client GetClientRecord(NetPeer peer)
55 | {
56 | Client client = ClientToNetPeerMap.First(o => o.Value == peer).Key;
57 | return client;
58 | }
59 |
60 | public void OnClientConnect(Action callBack)
61 | {
62 | onConnectCallBack = callBack;
63 | if (ClientToNetPeerMap.Count() > 0)
64 | onConnectCallBack.Invoke(ClientToNetPeerMap.First().Key);
65 | }
66 |
67 | public void OnReceive(Action callBack)
68 | {
69 | onReceiveCallback = callBack;
70 | }
71 |
72 | public void OnClientDisconnect(Action callBack)
73 | {
74 | onDisconnectCallBack = callBack;
75 | }
76 |
77 | public void SetReliable()
78 | {
79 | ReliableTransport = true;
80 | }
81 |
82 | public void SetUnreliable()
83 | {
84 | ReliableTransport = false;
85 | }
86 |
87 | public void Send(Client client, string payload)
88 | {
89 | var netPeer = this.ClientToNetPeerMap[client];
90 |
91 | NetDataWriter writer = new NetDataWriter();
92 | writer.Put(payload);
93 | if (ReliableTransport)
94 | netPeer.Send(writer, SendOptions.ReliableOrdered);
95 | else
96 | netPeer.Send(writer, SendOptions.Sequenced);
97 | }
98 |
99 | public void DisconnectClient(params Client[] clients)
100 | {
101 | //This is the client so stop the connection completely.
102 | Stop();
103 | }
104 |
105 | public void Start(string ipaddress, int port)
106 | {
107 | listener = new EventBasedNetListener();
108 | clientUDP = new NetManager(listener, "ConnectionKey");
109 | clientUDP.UnsyncedEvents = true;
110 | clientUDP.Start();
111 | clientUDP.Connect(ipaddress, port);
112 |
113 | listener.PeerDisconnectedEvent += (c,i) =>
114 | {
115 | Client client = GetClientRecord(c);
116 | onDisconnectCallBack.Invoke(client);
117 | };
118 |
119 | listener.PeerConnectedEvent += c =>
120 | {
121 | Client client = new Client(c.EndPoint.Host, c.EndPoint.Port);
122 | ClientToNetPeerMap.Add(client, c);
123 | onConnectCallBack?.Invoke(client);
124 | };
125 |
126 | listener.NetworkReceiveEvent += (fromPeer, dataReader) =>
127 | {
128 | Client client = GetClientRecord(fromPeer);
129 | var payload = dataReader.GetString();
130 | ReceivedMessage receivedMessage = new ReceivedMessage(client, payload);
131 | onReceiveCallback.Invoke(receivedMessage);
132 | };
133 |
134 | clientUDP.PollEvents();
135 |
136 | WaitTillConnectionMade();
137 | this._LocalPort = clientUDP.LocalPort;
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/Implementation/ObjectTransport.UDP/UDPServerChannel.cs:
--------------------------------------------------------------------------------
1 | using LiteNetLib;
2 | using LiteNetLib.Utils;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Net.Sockets;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace OTransport.NetworkChannel.UDP
13 | {
14 | public class UDPServerChannel : INetworkChannel
15 | {
16 | private Dictionary ClientToNetPeerMap = new Dictionary();
17 | private IPAddress IPAddress;
18 |
19 | private EventBasedNetListener listener;
20 | private NetManager server;
21 |
22 | private bool ReliableTransport = false;
23 | private int _LocalPort;
24 | public int LocalPort { get { return _LocalPort; } }
25 |
26 |
27 | List clientTasks = new List();
28 | Action onReceiveCallback = null;
29 | Action onConnectCallBack = null;
30 | Action onDisconnectCallBack = null;
31 |
32 |
33 | public void Stop()
34 | {
35 | foreach (var keypair in ClientToNetPeerMap)
36 | {
37 | server.DisconnectPeer(keypair.Value);
38 | server.Stop();
39 | }
40 | }
41 | private Client GetClientRecord(NetPeer peer)
42 | {
43 | Client client = ClientToNetPeerMap.First(o => o.Value == peer).Key;
44 | return client;
45 | }
46 |
47 | public void OnClientConnect(Action callBack)
48 | {
49 | onConnectCallBack = callBack;
50 | }
51 |
52 | public void OnReceive(Action callBack)
53 | {
54 | onReceiveCallback = callBack;
55 | }
56 |
57 | public void OnClientDisconnect(Action callBack)
58 | {
59 | onDisconnectCallBack = callBack;
60 | }
61 |
62 | public void SetReliable()
63 | {
64 | ReliableTransport = true;
65 | }
66 |
67 | public void SetUnreliable()
68 | {
69 | ReliableTransport = false;
70 | }
71 |
72 | public void Send(Client client, string payload)
73 | {
74 | var netPeer = this.ClientToNetPeerMap[client];
75 | NetDataWriter writer = new NetDataWriter();
76 | writer.Put(payload);
77 |
78 | if(ReliableTransport)
79 | netPeer.Send(writer,SendOptions.ReliableOrdered);
80 | else
81 | netPeer.Send(writer,SendOptions.Sequenced);
82 | }
83 |
84 | public void DisconnectClient(params Client[] clients)
85 | {
86 | foreach(Client client in clients)
87 | {
88 | var netPeer = ClientToNetPeerMap[client];
89 | server.DisconnectPeer(netPeer);
90 | }
91 | }
92 |
93 | public void Start(string ipaddress, int port)
94 | {
95 | listener = new EventBasedNetListener();
96 | //Create a new server and only allow 32 connections
97 | server = new NetManager(listener, 32, "ConnectionKey");
98 | server.UnsyncedEvents = true;
99 | server.Start(port);
100 | _LocalPort = server.LocalPort;
101 |
102 | listener.PeerDisconnectedEvent += (c,i) =>
103 | {
104 | Client client = GetClientRecord(c);
105 | onDisconnectCallBack?.Invoke(client);
106 | };
107 |
108 | listener.PeerConnectedEvent += c =>
109 | {
110 | Client client = new Client(c.EndPoint.Host, c.EndPoint.Port);
111 | ClientToNetPeerMap.Add(client, c);
112 | onConnectCallBack?.Invoke(client);
113 | };
114 |
115 | listener.NetworkReceiveEvent += (fromPeer, dataReader) =>
116 | {
117 | Client client = GetClientRecord(fromPeer);
118 | var payload = dataReader.GetString();
119 | ReceivedMessage receivedMessage = new ReceivedMessage(client, payload);
120 | onReceiveCallback.Invoke(receivedMessage);
121 | };
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Rhyno van der Sluijs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LICENSE.LiteNetLib.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ruslan Pyrch
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/ObjectTransport.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.12
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectTransport", "ObjectTransport\ObjectTransport.csproj", "{050C5519-2C8F-4F8D-BBB6-1D23439B372B}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demos", "Demos", "{64660A3D-B48E-4CB7-BA05-125D15D19B26}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectTransport.Test", "ObjectTransport.tests\ObjectTransport.Test.csproj", "{4AC2E216-9F30-4B10-AF9F-A620D50268D4}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Implementation", "Implementation", "{73435E1E-498B-4E04-B7BD-9B03B9E59839}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectTransport.TCP", "Implementation\ObjectTransport.TCP\ObjectTransport.TCP.csproj", "{2C9790A6-D016-415C-B2AD-3F3AC0FFB53E}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectTransport.UDP", "Implementation\ObjectTransport.UDP\ObjectTransport.UDP.csproj", "{4F86BC9F-6557-41AA-B831-927ED23E03D5}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectTransport.JSON", "Implementation\ObjectTransport.Serializer.JSON\ObjectTransport.JSON.csproj", "{4E0C0A18-9DA4-4FAE-B11D-1C074DDC8CE0}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectTransport.Protobuf", "Implementation\ObjectTransport.Serializer.protobuf\ObjectTransport.Protobuf.csproj", "{515213C7-7358-4E13-B1B1-B60BA6C2EB21}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Messenger", "Demos\Messenger\Messenger.csproj", "{C9896DEA-3DDC-4F5B-B48E-2359DD01B951}"
23 | EndProject
24 | Global
25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
26 | Debug|Any CPU = Debug|Any CPU
27 | Release|Any CPU = Release|Any CPU
28 | EndGlobalSection
29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
30 | {050C5519-2C8F-4F8D-BBB6-1D23439B372B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {050C5519-2C8F-4F8D-BBB6-1D23439B372B}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {050C5519-2C8F-4F8D-BBB6-1D23439B372B}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {050C5519-2C8F-4F8D-BBB6-1D23439B372B}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {4AC2E216-9F30-4B10-AF9F-A620D50268D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {4AC2E216-9F30-4B10-AF9F-A620D50268D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {4AC2E216-9F30-4B10-AF9F-A620D50268D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {4AC2E216-9F30-4B10-AF9F-A620D50268D4}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {2C9790A6-D016-415C-B2AD-3F3AC0FFB53E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {2C9790A6-D016-415C-B2AD-3F3AC0FFB53E}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {2C9790A6-D016-415C-B2AD-3F3AC0FFB53E}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {2C9790A6-D016-415C-B2AD-3F3AC0FFB53E}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {4F86BC9F-6557-41AA-B831-927ED23E03D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {4F86BC9F-6557-41AA-B831-927ED23E03D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {4F86BC9F-6557-41AA-B831-927ED23E03D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {4F86BC9F-6557-41AA-B831-927ED23E03D5}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {4E0C0A18-9DA4-4FAE-B11D-1C074DDC8CE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {4E0C0A18-9DA4-4FAE-B11D-1C074DDC8CE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {4E0C0A18-9DA4-4FAE-B11D-1C074DDC8CE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {4E0C0A18-9DA4-4FAE-B11D-1C074DDC8CE0}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {515213C7-7358-4E13-B1B1-B60BA6C2EB21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {515213C7-7358-4E13-B1B1-B60BA6C2EB21}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {515213C7-7358-4E13-B1B1-B60BA6C2EB21}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {515213C7-7358-4E13-B1B1-B60BA6C2EB21}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {C9896DEA-3DDC-4F5B-B48E-2359DD01B951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {C9896DEA-3DDC-4F5B-B48E-2359DD01B951}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {C9896DEA-3DDC-4F5B-B48E-2359DD01B951}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {C9896DEA-3DDC-4F5B-B48E-2359DD01B951}.Release|Any CPU.Build.0 = Release|Any CPU
58 | EndGlobalSection
59 | GlobalSection(SolutionProperties) = preSolution
60 | HideSolutionNode = FALSE
61 | EndGlobalSection
62 | GlobalSection(NestedProjects) = preSolution
63 | {2C9790A6-D016-415C-B2AD-3F3AC0FFB53E} = {73435E1E-498B-4E04-B7BD-9B03B9E59839}
64 | {4F86BC9F-6557-41AA-B831-927ED23E03D5} = {73435E1E-498B-4E04-B7BD-9B03B9E59839}
65 | {4E0C0A18-9DA4-4FAE-B11D-1C074DDC8CE0} = {73435E1E-498B-4E04-B7BD-9B03B9E59839}
66 | {515213C7-7358-4E13-B1B1-B60BA6C2EB21} = {73435E1E-498B-4E04-B7BD-9B03B9E59839}
67 | {C9896DEA-3DDC-4F5B-B48E-2359DD01B951} = {64660A3D-B48E-4CB7-BA05-125D15D19B26}
68 | EndGlobalSection
69 | GlobalSection(ExtensibilityGlobals) = postSolution
70 | SolutionGuid = {72829232-B072-42DE-A6EE-57F7557CFF03}
71 | EndGlobalSection
72 | EndGlobal
73 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/NetworkChannel.tests/INetworkChannelGenericTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using OTransport.Test.Utilities;
3 | using OTransport.tests;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using Test;
9 |
10 | namespace OTransport
11 | {
12 | [TestClass]
13 | public abstract class INetworkChannelGenericTests
14 | {
15 | protected INetworkChannel Client1 { get; set; }
16 | protected INetworkChannel Client2 { get; set; }
17 | protected INetworkChannel Server { get; set; }
18 | protected List ServerOnConnectClients { get; set; }
19 | protected List ServerOnDisconnectClients { get; set; }
20 | protected List Client1OnConnectClients { get; set; }
21 | protected List Client1OnDisconnectClients { get; set; }
22 | protected IObjectTransport Client1ObjectTransport { get; set; }
23 | protected IObjectTransport serverObjectTransport { get; set; }
24 |
25 | protected void SetUpNetworkChannels(INetworkChannel client,INetworkChannel client2,INetworkChannel server)
26 | {
27 | Client1 = client;
28 | Client2 = client2;
29 | Server = server;
30 |
31 | ServerOnConnectClients = new List();
32 | ServerOnDisconnectClients = new List();
33 | Client1OnConnectClients = new List();
34 | Client1OnDisconnectClients = new List();
35 |
36 | serverObjectTransport = TestObjectTransportFactory.CreateNewObjectTransport(Server);
37 | serverObjectTransport.OnClientConnect(c => ServerOnConnectClients.Add(c));
38 | serverObjectTransport.OnClientDisconnect(c => ServerOnDisconnectClients.Add(c));
39 | serverObjectTransport.Start("127.0.0.1", 0);
40 |
41 | Utilities.WaitFor(()=> server.LocalPort !=0);
42 |
43 | Client1ObjectTransport = TestObjectTransportFactory.CreateNewObjectTransport(Client1);
44 | Client1ObjectTransport.OnClientConnect(c => Client1OnConnectClients.Add(c));
45 | Client1ObjectTransport.OnClientDisconnect(c => Client1OnDisconnectClients.Add(c));
46 | Client1ObjectTransport.Start("127.0.0.1", Server.LocalPort);
47 |
48 | //Wait for the connection to have been made
49 | Utilities.WaitFor(()=> serverObjectTransport.GetConnectedClients().Count() == 1);
50 | Utilities.WaitFor(()=> Client1ObjectTransport.GetConnectedClients().Count() == 1);
51 | }
52 | [TestMethod]
53 | public void ClientDisconnects_CallbackCalled()
54 | {
55 | //Arrange
56 | Client client = null;
57 | Client clientDisconnect = null;
58 |
59 | client = Client1ObjectTransport.GetConnectedClients().First();
60 |
61 | //Act
62 | serverObjectTransport.Stop();
63 |
64 | Utilities.WaitFor(()=> Client1OnDisconnectClients.Count() > 0);
65 | clientDisconnect = Client1OnDisconnectClients.First();
66 |
67 | //Assert
68 | Assert.AreEqual(client.IPAddress, "127.0.0.1");
69 | Assert.AreEqual(clientDisconnect.IPAddress, "127.0.0.1");
70 | Assert.AreEqual(clientDisconnect,client);
71 | Utilities.WaitFor(()=>Client1ObjectTransport.GetConnectedClients().Count() == 0);
72 | Utilities.WaitFor(()=>serverObjectTransport.GetConnectedClients().Count() == 0);
73 | }
74 | [TestMethod]
75 | public void Client_StartExecuted_ServerIsAddedAsClient()
76 | {
77 | //Arrange
78 | Client FirstClient = null;
79 |
80 | //Act
81 | FirstClient = Client1ObjectTransport.GetConnectedClients().First();
82 |
83 |
84 | //Assert
85 | Assert.AreEqual(FirstClient.IPAddress, "127.0.0.1");
86 | Assert.AreEqual(FirstClient.Port, Server.LocalPort);
87 | }
88 |
89 | [TestMethod]
90 | public void SendAndReplyMessage_ResponseIsCalled()
91 | {
92 | //Arrange
93 | Client client = null;
94 | client = Client1ObjectTransport.GetConnectedClients().First();
95 |
96 | //Act
97 | serverObjectTransport.Receive()
98 | .Reply((o) => { return o; })
99 | .Execute();
100 |
101 | var mockObject = new MockObjectMessage() { Property1_string = "Mock Object" };
102 | MockObjectMessage responseObject = null;
103 |
104 | Client1ObjectTransport.Send(mockObject)
105 | .Response((r) => {responseObject = r;})
106 | .Execute();
107 |
108 | Utilities.WaitFor(ref responseObject);
109 |
110 | //Assert
111 | Assert.AreEqual(responseObject.Property1_string, "Mock Object");
112 | }
113 |
114 | [TestMethod]
115 | public void ClientDisconnectsServer_ServerOnClientDisconnectCalled()
116 | {
117 | //Arrange
118 | //Create a second client
119 | ObjectTransport clientObjectTransport2 = TestObjectTransportFactory.CreateNewObjectTransport(Client2);
120 | clientObjectTransport2.Start("127.0.0.1", Server.LocalPort);
121 |
122 | //Wait for the connection to have been made
123 | Utilities.WaitFor(() => serverObjectTransport.GetConnectedClients().Count() == 2);
124 |
125 | //Act
126 |
127 | //disconnect the server from the client
128 | Client1ObjectTransport.DisconnectClient();
129 |
130 | Utilities.WaitFor(()=> ServerOnDisconnectClients.Count ==1);
131 |
132 | //Assert
133 | //Ensure that the client record was disconnect from the server
134 | Assert.AreEqual(1,serverObjectTransport.GetConnectedClients().Count());
135 |
136 | //Esnure that the client who disconnected from the server was the one that we called disconect
137 | Assert.AreEqual(ServerOnDisconnectClients.First().Port, Client1.LocalPort);
138 | }
139 |
140 | [TestMethod]
141 | public void Server_ClientDisconnects_CallbackCalled()
142 | {
143 | //Arrange
144 |
145 | //Act
146 |
147 | Client1ObjectTransport.Stop();
148 | Utilities.WaitFor(()=> ServerOnDisconnectClients.Count() == 1);
149 |
150 | //Assert
151 | var clientConnect = ServerOnConnectClients.First();
152 | var clientDisconnect = ServerOnDisconnectClients.First();
153 | Assert.AreEqual(clientConnect.IPAddress, "127.0.0.1");
154 | Assert.AreEqual(clientDisconnect.IPAddress, "127.0.0.1");
155 | Assert.AreEqual(clientDisconnect,clientConnect);
156 | Assert.AreEqual(0,Client1ObjectTransport.GetConnectedClients().Count());
157 | Assert.AreEqual(0,serverObjectTransport.GetConnectedClients().Count());
158 | }
159 |
160 | [TestMethod]
161 | public void ServerWith2Clients_ServerDisconnects1Client_1ClientDisconnected()
162 | {
163 | //Arrange
164 | ObjectTransport clientObjectTransport2 = TestObjectTransportFactory.CreateNewObjectTransport(Client2);
165 | clientObjectTransport2.Start("127.0.0.1", Server.LocalPort);
166 |
167 | //Wait for the connection to have been made
168 | Utilities.WaitFor(() => serverObjectTransport.GetConnectedClients().Count() == 2);
169 | var FirstClient = serverObjectTransport.GetConnectedClients().First();
170 |
171 | //Act
172 |
173 | serverObjectTransport.DisconnectClient(FirstClient);
174 | Utilities.WaitFor(()=> ServerOnDisconnectClients.Count() ==1);
175 |
176 | //Assert
177 |
178 | Client LastClient = serverObjectTransport.GetConnectedClients().First();
179 | Assert.AreEqual(1, serverObjectTransport.GetConnectedClients().Count());
180 | Assert.AreNotEqual(FirstClient.Port, LastClient.Port);
181 | }
182 | [TestMethod]
183 | public void ServerWith2Clients_ServerDisconnects2Client_AllClientsDisconnected()
184 | {
185 | //Arrange
186 |
187 | //Create a second client
188 | ObjectTransport clientObjectTransport2 = TestObjectTransportFactory.CreateNewObjectTransport(Client2);
189 | clientObjectTransport2.Start("127.0.0.1", Server.LocalPort);
190 |
191 | //Wait for the connection to have been made
192 | Utilities.WaitFor(() => serverObjectTransport.GetConnectedClients().Count() == 2);
193 |
194 | //Act
195 |
196 | var allClients = serverObjectTransport.GetConnectedClients().ToArray();
197 | serverObjectTransport.DisconnectClient(allClients);
198 |
199 | Utilities.WaitFor(() => ServerOnDisconnectClients.Count == 2);
200 |
201 | //Assert
202 | Assert.AreEqual(0, serverObjectTransport.GetConnectedClients().Count());
203 | Assert.AreEqual(2, ServerOnDisconnectClients.Count());
204 | }
205 |
206 | [TestMethod]
207 | public void Server_ReceivesObjects_CorrectObjectReceived()
208 | {
209 | //Arrange
210 | MockObjectMessage receivedObject = null;
211 |
212 | //Act
213 | serverObjectTransport.Receive(o =>
214 | {
215 | receivedObject = o;
216 |
217 | }).Execute();
218 |
219 | Client1ObjectTransport.Send(new MockObjectMessage()
220 | {
221 | Property1_string = "hello world!",
222 | Property2_int = 123,
223 | Property3_decimal = 12.3M
224 | }).Execute();
225 |
226 | Utilities.WaitFor(ref receivedObject);
227 |
228 | //Assert
229 | Assert.AreEqual("hello world!", receivedObject.Property1_string);
230 | Assert.AreEqual(123, receivedObject.Property2_int);
231 | Assert.AreEqual(12.3M, receivedObject.Property3_decimal);
232 | }
233 |
234 | [TestMethod]
235 | public void Server_SendObject_CorrectObjectSent()
236 | {
237 | //Arrange
238 | MockObjectMessage receivedObject = null;
239 |
240 | Client client = serverObjectTransport.GetConnectedClients().First();
241 |
242 | //Act
243 | Client1ObjectTransport.Receive(o =>
244 | receivedObject = o
245 | ).Execute();
246 |
247 | serverObjectTransport.Send(new MockObjectMessage()
248 | {
249 | Property1_string = "hello world!",
250 | Property2_int = 123,
251 | Property3_decimal = 12.3M
252 |
253 | })
254 | .To(client)
255 | .Execute();
256 |
257 | Utilities.WaitFor(ref receivedObject);
258 |
259 | //Assert
260 | Assert.AreEqual("hello world!", receivedObject.Property1_string);
261 | Assert.AreEqual(123, receivedObject.Property2_int);
262 | Assert.AreEqual(12.3M, receivedObject.Property3_decimal);
263 | }
264 |
265 |
266 | [TestMethod]
267 | public void Server_WhenClientConnects_CallbackFunctionCalled()
268 | {
269 | Assert.AreEqual(serverObjectTransport.GetConnectedClients().Count(), 1);
270 | }
271 |
272 | [TestMethod]
273 | public void Server_ServerDisconnects2Client_AllClientsDisconnected()
274 | {
275 | //Arrange
276 |
277 | //Create a second client
278 | ObjectTransport clientObjectTransport2 = TestObjectTransportFactory.CreateNewObjectTransport(Client2);
279 | clientObjectTransport2.Start("127.0.0.1", Server.LocalPort);
280 |
281 | //Wait for the connection to have been made
282 | Utilities.WaitFor(() => serverObjectTransport.GetConnectedClients().Count() == 2);
283 |
284 | //Act
285 |
286 | var allClients = serverObjectTransport.GetConnectedClients().ToArray();
287 | serverObjectTransport.DisconnectClient(allClients);
288 |
289 | Utilities.WaitFor(() => ServerOnDisconnectClients.Count == 2);
290 |
291 | //Assert
292 | Assert.AreEqual(0, serverObjectTransport.GetConnectedClients().Count());
293 | Assert.AreEqual(2, ServerOnDisconnectClients.Count());
294 | }
295 |
296 | [TestMethod]
297 | [Ignore]
298 | public void Send_TwoObjectsStraightAway_BothProcessedSeperatly()
299 | {
300 | //Arrange
301 | Client client = null;
302 | client = Client1ObjectTransport.GetConnectedClients().First();
303 |
304 | //Act
305 | serverObjectTransport.Receive()
306 | .Reply((o) => { return o; })
307 | .Execute();
308 |
309 | var mockObject = new MockObjectMessage() { Property1_string = "Mock Object" };
310 | MockObjectMessage responseObject = null;
311 | MockObjectMessage responseObject2 = null;
312 |
313 | Client1ObjectTransport.Send(mockObject)
314 | .Response((r) => {responseObject = r;})
315 | .Execute();
316 |
317 | Client1ObjectTransport.Send(mockObject)
318 | .Response((r) => {responseObject2 = r;})
319 | .Execute();
320 |
321 | Utilities.WaitFor(ref responseObject);
322 | Utilities.WaitFor(ref responseObject2);
323 |
324 | //Assert
325 | Assert.AreEqual(responseObject.Property1_string, "Mock Object");
326 | Assert.AreEqual(responseObject2.Property1_string, "Mock Object");
327 | }
328 |
329 | [TestCleanup]
330 | public void ShutDownNetworkChannels()
331 | {
332 | Server.Stop();
333 | Client1.Stop();
334 | Client2.Stop();
335 | }
336 |
337 | }
338 | }
339 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/NetworkChannel.tests/TCPNetworkChannelGenericTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using OTransport;
3 | using OTransport.NetworkChannel.TCP;
4 | using OTransport.Test.Utilities;
5 | using OTransport.tests;
6 | using System;
7 | using System.Linq;
8 | using Test;
9 |
10 | namespace OTranport
11 | {
12 | [TestClass]
13 | public class TCPNetworkChannelGenericTests : INetworkChannelGenericTests
14 | {
15 | [TestInitialize]
16 | public void SetUpNetworkChannels()
17 | {
18 | SetUpNetworkChannels(new TCPClientChannel(), new TCPClientChannel(), new TCPServerChannel());
19 | }
20 | [TestMethod]
21 | [ExpectedException(typeof(NotSupportedException))]
22 | public void TCPClient_SendUnreliably_ExceptionThrown()
23 | {
24 | //Arrange
25 | Client client = null;
26 | Client clientDisconnect = null;
27 |
28 | ObjectTransport serverObjectTransport = TestObjectTransportFactory.CreateNewObjectTransport(Server);
29 | serverObjectTransport.Start("127.0.0.1", 0);
30 |
31 | ObjectTransport clientObjectTransport = TestObjectTransportFactory.CreateNewObjectTransport(Client1);
32 | clientObjectTransport.OnClientDisconnect(c => clientDisconnect = c);
33 | clientObjectTransport.Start("127.0.0.1", Server.LocalPort);
34 |
35 | Utilities.WaitFor(() => serverObjectTransport.GetConnectedClients().Count() == 1);
36 |
37 | client = clientObjectTransport.GetConnectedClients().First();
38 | Utilities.WaitFor(ref client);
39 |
40 | var message = new MockObjectMessage();
41 | //Act
42 |
43 | clientObjectTransport.Send(message)
44 | .Unreliable()
45 | .Execute();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/NetworkChannel.tests/UDPNetworkChannelGenericTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using OTransport;
3 | using OTransport.NetworkChannel.TCP;
4 | using OTransport.NetworkChannel.UDP;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Text;
8 |
9 | namespace OTranport
10 | {
11 | [TestClass]
12 | public class UDPNetworkChannelGenericTests : INetworkChannelGenericTests
13 | {
14 | [TestInitialize]
15 | public void SetUpNetworkChannels()
16 | {
17 | SetUpNetworkChannels(new UDPClientChannel(), new UDPClientChannel(), new UDPServerChannel());
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/NetworkChannel.tests/Utilities/TCPNetworkChannelFactory.cs:
--------------------------------------------------------------------------------
1 | using OTransport.NetworkChannel.TCP;
2 | using OTransport;
3 | using OTransport.Test.Utilities;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Text;
7 | using System.Threading;
8 |
9 | namespace Test
10 | {
11 | class TCPObjectTransportChannel
12 | {
13 | private static TCPServerChannel server = new TCPServerChannel();
14 | private static TCPClientChannel tcpclient = new TCPClientChannel();
15 | public static Tuple GetConnectObjectTransports()
16 | {
17 | server.Start("127.0.0.1", 0);
18 |
19 | ObjectTransport serverObjectTransport = TestObjectTransportFactory.CreateNewObjectTransport(server);
20 |
21 | tcpclient.Start("127.0.0.1", server.LocalPort);
22 | ObjectTransport client = TestObjectTransportFactory.CreateNewObjectTransport(tcpclient);
23 |
24 | Tuple result = new Tuple(serverObjectTransport, client);
25 | return result;
26 | }
27 | public static void TearDown()
28 | {
29 | if (server != null)
30 | server.Stop();
31 | if (tcpclient != null)
32 | tcpclient.Stop();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/ObjectTransport.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp1.1
5 |
6 | false
7 |
8 | ObjectTransport.Test
9 |
10 | ObjectTransport.Test
11 | PackageReference
12 | true
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/ObjectTransport_OnConnect.tests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using OTransport.Test.Utilities;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using Test;
7 |
8 | namespace OTransport.tests
9 | {
10 | [TestClass]
11 | public class ObjectTransport_OnConnect
12 | {
13 | [TestMethod]
14 | public void OnClientConnect_ClientConnectsToObject_ClientInjectedIntoAction()
15 | {
16 | //Arrange
17 | var sentJson = string.Empty;
18 | var client = new Client("10.0.0.1",123);
19 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel();
20 |
21 | Client connectedClient = null;
22 |
23 | //Act
24 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
25 | transport.OnClientConnect(c =>
26 | {
27 | connectedClient = c;
28 | });
29 |
30 | networkChannel.SimulateClientConnect(client);
31 | //Assert
32 | Assert.AreEqual(client, connectedClient);
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/ObjectTransport_Receive.tests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System.Text.RegularExpressions;
4 | using Test;
5 | using System.Text;
6 | using OTransport.Test.Utilities;
7 |
8 | namespace OTransport.tests
9 | {
10 | [TestClass]
11 | public class ObjectTransport_Receive
12 | {
13 |
14 | [TestMethod]
15 | public void Receive_ObjectType_ObjectReceiveFunctionExecuted()
16 | {
17 | //Arrange
18 |
19 | Client client = new Client("10.0.0.1",123);
20 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel();
21 |
22 | MockObjectMessage receive = new MockObjectMessage();
23 |
24 | //Act
25 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
26 | transport.Receive(o =>
27 | {
28 | receive = o;
29 | }
30 | )
31 | .Execute();
32 |
33 | networkChannel.SimulateClientConnect(client);
34 | networkChannel.SimulateClientResponse(client,
35 | "OTransport.tests.MockObjectMessage, ObjectTransport.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null::{\"Property1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}"
36 | );
37 | //Assert
38 | Assert.AreEqual("Test String", receive.Property1_string);
39 | Assert.AreEqual(12, receive.Property2_int);
40 | Assert.AreEqual(1.33M, receive.Property3_decimal);
41 | }
42 | [TestMethod]
43 | public void Receive_InvalidObjectType_ObjectNotProcessed()
44 | {
45 | //Arrange
46 |
47 | Client client = new Client("10.0.0.1", 123);
48 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel();
49 |
50 | MockObjectMessage receive = new MockObjectMessage();
51 |
52 | //Act
53 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
54 | transport.Receive(o =>
55 | {
56 | receive = o;
57 | }
58 | )
59 | .Execute();
60 |
61 | networkChannel.SimulateClientConnect(client);
62 | networkChannel.SimulateClientResponse(client, "OTransport.tests.NOTHING, ObjectTransport.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null::{\"Property1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}");
63 | }
64 |
65 | [TestMethod]
66 | public void Receive_InvalidPayload_PayloadNotProcessed()
67 | {
68 | //Arrange
69 |
70 | Client client = new Client("10.0.0.1",123);
71 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel();
72 |
73 | MockObjectMessage receive = null;
74 |
75 | //Act
76 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
77 | transport.Receive(o =>
78 | {
79 | receive = o;
80 | }
81 | )
82 | .Execute();
83 |
84 | networkChannel.SimulateClientConnect(client);
85 | networkChannel.SimulateClientResponse(client,
86 | "{\"Type\":\"OTransport.tests.MockObjectMessage, ObjectTransport.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\",:{\"Property1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}}"
87 | );
88 |
89 | //Assert
90 | Assert.IsNull(receive);
91 | }
92 |
93 | [TestMethod]
94 | [ExpectedException(typeof(ObjectTransportException))]
95 | public void Receve_RegisterSameTypeTwice_ObjectTransportExceptionThrown()
96 | {
97 | //Arrange
98 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel();
99 |
100 | //Act
101 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
102 | transport.Receive().Execute();
103 | transport.Receive().Execute();
104 | }
105 |
106 | [TestMethod]
107 | public void Receive_ReplyToReceivedObject_ObjectIsSentBack()
108 | {
109 | //Arrange
110 | string replayPayload = null;
111 | Client client = new Client("10.0.0.1",123);
112 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
113 | .OnSendHandle((Client, payload) => replayPayload = payload);
114 |
115 |
116 | //Act
117 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
118 | transport.Receive()
119 | .Reply(o=>
120 | {
121 | MockObjectMessage sendBack = new MockObjectMessage();
122 | sendBack.Property1_string = "Reply message";
123 | sendBack.Property2_int = 12;
124 | sendBack.Property3_decimal = 1.33M;
125 |
126 | return sendBack;
127 |
128 | })
129 | .Execute();
130 |
131 |
132 | networkChannel.SimulateClientConnect(client);
133 | networkChannel.SimulateClientResponse(client,
134 | "OTransport.tests.MockObjectMessage, ObjectTransport.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null::{\"Property1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}"
135 | );
136 |
137 | //Assert
138 | Assert.AreEqual( "OTransport.tests.MockObjectMessage, ObjectTransport.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null::{\"Property1_string\":\"Reply message\",\"Property2_int\":12,\"Property3_decimal\":1.33}" , replayPayload);
139 | }
140 |
141 | [TestMethod]
142 | public void SendReceiveThroughChannel_ObjectTransportConnectedChannel_ObjectSentAndReceivedBetweenClients()
143 | {
144 | //Arrange
145 | var joinedNetworkChannels = MockNetworkChannelFactory.GetConnectedChannels();
146 |
147 | MockObjectMessage sendMessage = new MockObjectMessage();
148 | sendMessage.Property1_string = "test send";
149 | sendMessage.Property2_int = 123;
150 | sendMessage.Property3_decimal = 56M;
151 |
152 | MockObjectMessage receivedMessage = null;
153 |
154 | //Act
155 | ObjectTransport client1 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item1);
156 | client1.Receive(o=>
157 | {
158 | receivedMessage = o;
159 | })
160 | .Execute();
161 |
162 |
163 | ObjectTransport client2 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item2);
164 | client2.Send(sendMessage)
165 | .Execute();
166 |
167 | Utilities.WaitFor(ref receivedMessage);
168 |
169 | //Assert
170 | Assert.AreEqual(sendMessage.Property3_decimal, receivedMessage.Property3_decimal);
171 | Assert.AreEqual(sendMessage.Property1_string, receivedMessage.Property1_string);
172 | Assert.AreEqual(sendMessage.Property2_int, receivedMessage.Property2_int);
173 | }
174 |
175 | [TestMethod]
176 | public void Receive_WithClientAction_ObjectAndClientInjectedInAction()
177 | {
178 | //Arrange
179 | var joinedNetworkChannels = MockNetworkChannelFactory.GetConnectedChannels();
180 |
181 | MockObjectMessage sendMessage = new MockObjectMessage();
182 | sendMessage.Property1_string = "test send";
183 | sendMessage.Property2_int = 123;
184 | sendMessage.Property3_decimal = 56M;
185 |
186 | MockObjectMessage receivedMessage = null;
187 | Client receivedClient = null;
188 |
189 | //Act
190 | ObjectTransport client1 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item1);
191 | client1.Receive((c,o)=>
192 | {
193 | receivedClient = c;
194 | receivedMessage = o;
195 | })
196 | .Execute();
197 |
198 |
199 | ObjectTransport client2 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item2);
200 | client2.Send(sendMessage)
201 | .Execute();
202 |
203 | //Assert
204 | Assert.AreEqual(sendMessage.Property3_decimal, receivedMessage.Property3_decimal);
205 | Assert.AreEqual(sendMessage.Property1_string, receivedMessage.Property1_string);
206 | Assert.AreEqual(sendMessage.Property2_int, receivedMessage.Property2_int);
207 | Assert.AreEqual("10.0.0.2", receivedClient.IPAddress);
208 | }
209 |
210 | [TestMethod]
211 | public void ReceiveReply_WithClientAction_ObjectAndClientInjectedInToAction()
212 | {
213 | //Arrange
214 | var joinedNetworkChannels = MockNetworkChannelFactory.GetConnectedChannels();
215 |
216 | MockObjectMessage sendMessage = new MockObjectMessage();
217 | sendMessage.Property1_string = "test send";
218 | sendMessage.Property2_int = 123;
219 | sendMessage.Property3_decimal = 56M;
220 |
221 | MockObjectMessage receivedMessage = null;
222 | Client receivedClient = null;
223 |
224 | //Act
225 | ObjectTransport client1 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item1);
226 | client1.Receive()
227 | .Reply((c,o) =>
228 | {
229 | receivedMessage = o;
230 | receivedClient = c;
231 | return null;
232 | })
233 | .Execute();
234 |
235 |
236 | ObjectTransport client2 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item2);
237 | client2.Send(sendMessage)
238 | .Execute();
239 |
240 | Utilities.WaitFor(ref receivedMessage);
241 |
242 | //Assert
243 | Assert.AreEqual(sendMessage.Property3_decimal, receivedMessage.Property3_decimal);
244 | Assert.AreEqual(sendMessage.Property1_string, receivedMessage.Property1_string);
245 | Assert.AreEqual(sendMessage.Property2_int, receivedMessage.Property2_int);
246 | Assert.AreEqual("10.0.0.2", receivedClient.IPAddress);
247 | }
248 |
249 | [TestMethod]
250 | public void SendReceiveReplyThroughChannel_TwoObjectTransportsConnected_SameTokenUsed()
251 | {
252 | //Arrange
253 | var client2ReceiveFunctionCalled = false;
254 | var client2RespondFunctionCalled = false;
255 | var joinedNetworkChannels = MockNetworkChannelFactory.GetConnectedChannels();
256 |
257 | MockObjectMessage sendMessage = new MockObjectMessage();
258 | sendMessage.Property1_string = "test send";
259 | sendMessage.Property2_int = 123;
260 | sendMessage.Property3_decimal = 56M;
261 |
262 | MockObjectMessage receivedMessage = null;
263 |
264 | //Act
265 | ObjectTransport client1 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item1);
266 | client1.Receive()
267 | .Reply((c,o) =>
268 | {
269 | o.Property1_string = "replied";
270 | return o;
271 | })
272 | .Execute();
273 |
274 |
275 | ObjectTransport client2 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item2);
276 | client2.Send(sendMessage)
277 | .Response(o =>
278 | {
279 | client2RespondFunctionCalled = true;
280 | receivedMessage = o;
281 | })
282 | .Execute();
283 |
284 | client2.Receive(o =>
285 | {
286 | client2ReceiveFunctionCalled = true;
287 | receivedMessage = o;
288 | }).Execute();
289 |
290 | Utilities.WaitFor(ref receivedMessage);
291 |
292 | //Assert
293 | Assert.IsFalse(client2ReceiveFunctionCalled);
294 | Assert.IsTrue(client2RespondFunctionCalled);
295 | }
296 | [TestMethod]
297 | public void Receive_ObjectWithBinaryProperty_BinaryReceived()
298 | {
299 | //Arrange
300 | var joinedNetworkChannels = MockNetworkChannelFactory.GetConnectedChannels();
301 |
302 | MockObjectMessageWithBinary sendMessage = new MockObjectMessageWithBinary();
303 | sendMessage.Property2_String = "Message with binary";
304 | sendMessage.Property1_Bytes = Encoding.ASCII.GetBytes("hello world");
305 |
306 | MockObjectMessageWithBinary receivedMessage = null;
307 | Client receivedClient = null;
308 |
309 | //Act
310 | ObjectTransport client1 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item1);
311 | client1.Receive((c, o) =>
312 | {
313 | receivedClient = c;
314 | receivedMessage = o;
315 | })
316 | .Execute();
317 |
318 |
319 | ObjectTransport client2 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item2);
320 | client2.Send(sendMessage)
321 | .Execute();
322 |
323 | //Assert
324 | Assert.AreEqual("hello world", System.Text.Encoding.UTF8.GetString(receivedMessage.Property1_Bytes));
325 | Assert.AreEqual(receivedMessage.Property2_String, "Message with binary");
326 | Assert.AreEqual("10.0.0.2", receivedClient.IPAddress);
327 | }
328 |
329 | [TestMethod]
330 | public void OnFailedReceived_InvalidPayloadReceived_OnFailHandleExecuted()
331 | {
332 | //Arrange
333 |
334 | Client client = new Client("10.0.0.1", 123);
335 | ReceivedMessage receivedMessage = null;
336 | Exception failedException = null;
337 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel();
338 |
339 | MockObjectMessage receive = new MockObjectMessage();
340 |
341 | //Act
342 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
343 | transport.Receive(o =>
344 | {
345 | receive = o;
346 | }
347 | )
348 | .Execute();
349 |
350 | transport.OnFailedReceive((r, e) =>
351 | {
352 | receivedMessage = r;
353 | failedException = e;
354 | });
355 |
356 | networkChannel.SimulateClientConnect(client);
357 | networkChannel.SimulateClientResponse(client, "OTransport.tests.NOTHING, ObjectTransport.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullProperty1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}");
358 |
359 | Assert.IsNotNull(receivedMessage);
360 | Assert.IsNotNull(failedException);
361 | }
362 |
363 | }
364 | }
365 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/ObjectTransport_Send.tests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System.Text.RegularExpressions;
4 | using Test;
5 | using System.Collections.Generic;
6 | using System.Text;
7 | using OTransport.Test.Utilities;
8 |
9 | namespace OTransport.tests
10 | {
11 | [TestClass]
12 | public class ObjectTransport_Send
13 | {
14 | [TestMethod]
15 | public void SendExecute_ObjectWithProperties_PayloadWithObjectAndTypeSent()
16 | {
17 | //Arrange
18 | var sentPayload = string.Empty;
19 | var client = new Client("10.0.0.1",123);
20 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
21 | .OnSendHandle((Client, payload) => sentPayload = payload);
22 |
23 | MockObjectMessage sendObject = new MockObjectMessage();
24 | sendObject.Property1_string = "Test String";
25 | sendObject.Property2_int = 12;
26 | sendObject.Property3_decimal = 1.33M;
27 |
28 | //Act
29 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
30 | networkChannel.SimulateClientConnect(client);
31 | transport.Send(sendObject)
32 | .To(client)
33 | .Execute();
34 |
35 | //Assert
36 | Assert.AreEqual(typeof(MockObjectMessage).AssemblyQualifiedName + "::{\"Property1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}", sentPayload);
37 | }
38 | [TestMethod]
39 | public void SendWithResponse_ObjectWithPropertiesSet_PayloadWithObjectAndTokenSent()
40 | {
41 | //Arrange
42 | var sentPayload = string.Empty;
43 | var client = new Client("10.0.0.1",123);
44 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
45 | .OnSendHandle((Client, payload) => sentPayload = payload);
46 |
47 | MockObjectMessage sendObject = new MockObjectMessage();
48 | sendObject.Property1_string = "Test String";
49 | sendObject.Property2_int = 12;
50 | sendObject.Property3_decimal = 1.33M;
51 |
52 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
53 | networkChannel.SimulateClientConnect(client);
54 |
55 | //Act
56 |
57 | transport.Send(sendObject)
58 | .Response(o => o.GetType())
59 | .Execute();
60 |
61 |
62 | Utilities.WaitFor(ref sentPayload);
63 |
64 | //Assert
65 | Regex rgx = new Regex(typeof(MockObjectMessage).AssemblyQualifiedName + "::(.*)::{\"Property1_string\":\"Test String\",\"Property2_int\":12,\"Property3_decimal\":1.33}");
66 | Assert.IsTrue(rgx.IsMatch(sentPayload));
67 | }
68 |
69 | [TestMethod]
70 | public void SendToAll_AllClients_AllClientsAreSendTo()
71 | {
72 | //Arrange
73 | var client1 = new Client("10.0.0.1", 123);
74 | var client2 = new Client("10.0.0.2", 123);
75 | var client3 = new Client("10.0.0.3", 123);
76 |
77 | var clientsSendTo = new List();
78 |
79 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
80 | .OnSendHandle((Client, payload) => clientsSendTo.Add(Client));
81 |
82 | MockObjectMessage sendObject = new MockObjectMessage();
83 | sendObject.Property1_string = "Test String";
84 | sendObject.Property2_int = 12;
85 | sendObject.Property3_decimal = 1.33M;
86 |
87 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
88 |
89 | networkChannel.SimulateClientConnect(client1);
90 | networkChannel.SimulateClientConnect(client2);
91 | networkChannel.SimulateClientConnect(client3);
92 |
93 | //Act
94 |
95 | transport.Send(sendObject)
96 | .Response(o => o.GetType())
97 | .ToAll()
98 | .Execute();
99 |
100 | //Assert
101 | Assert.AreEqual(3, clientsSendTo.Count);
102 | Assert.AreEqual(clientsSendTo[0].IPAddress, "10.0.0.1");
103 | Assert.AreEqual(clientsSendTo[1].IPAddress, "10.0.0.2");
104 | Assert.AreEqual(clientsSendTo[2].IPAddress, "10.0.0.3");
105 |
106 | }
107 |
108 | [TestMethod]
109 | public void SendToAll_Except1Client_AllClientsExcept1AreSendTo()
110 | {
111 | //Arrange
112 | var client1 = new Client("10.0.0.1", 123);
113 | var client2 = new Client("10.0.0.2", 123);
114 | var client3 = new Client("10.0.0.3", 123);
115 |
116 | var clientsSendTo = new List();
117 |
118 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
119 | .OnSendHandle((Client, paylaod) => clientsSendTo.Add(Client));
120 |
121 | MockObjectMessage sendObject = new MockObjectMessage();
122 | sendObject.Property1_string = "Test String";
123 | sendObject.Property2_int = 12;
124 | sendObject.Property3_decimal = 1.33M;
125 |
126 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
127 |
128 | networkChannel.SimulateClientConnect(client1);
129 | networkChannel.SimulateClientConnect(client2);
130 | networkChannel.SimulateClientConnect(client3);
131 |
132 | //Act
133 |
134 | transport.Send(sendObject)
135 | .Response(o => o.GetType())
136 | .ToAllExcept(client1)
137 | .Execute();
138 |
139 | //Assert
140 | Assert.AreEqual(2, clientsSendTo.Count);
141 | Assert.AreEqual(clientsSendTo[0].IPAddress, "10.0.0.2");
142 | Assert.AreEqual(clientsSendTo[1].IPAddress, "10.0.0.3");
143 |
144 | }
145 |
146 | [TestMethod]
147 | public void SendToAll_Except2Client_AllClientsExcept2AreSendTo()
148 | {
149 | //Arrange
150 | var client1 = new Client("10.0.0.1", 123);
151 | var client2 = new Client("10.0.0.2", 123);
152 | var client3 = new Client("10.0.0.3", 123);
153 |
154 | var clientsSendTo = new List();
155 |
156 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
157 | .OnSendHandle((Client, paylaod) => clientsSendTo.Add(Client));
158 |
159 | MockObjectMessage sendObject = new MockObjectMessage();
160 | sendObject.Property1_string = "Test String";
161 | sendObject.Property2_int = 12;
162 | sendObject.Property3_decimal = 1.33M;
163 |
164 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
165 |
166 | networkChannel.SimulateClientConnect(client1);
167 | networkChannel.SimulateClientConnect(client2);
168 | networkChannel.SimulateClientConnect(client3);
169 |
170 | //Act
171 |
172 | transport.Send(sendObject)
173 | .Response(o => o.GetType())
174 | .ToAllExcept(client1,client3)
175 | .Execute();
176 |
177 | //Assert
178 | Assert.AreEqual(1, clientsSendTo.Count);
179 | Assert.AreEqual(clientsSendTo[0].IPAddress, "10.0.0.2");
180 |
181 | }
182 |
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/ObjectTransport_TimeOut.tests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System.Text.RegularExpressions;
4 | using Test;
5 | using System.Collections.Generic;
6 | using System.Text;
7 | using System.Linq;
8 | using OTransport.Test.Utilities;
9 |
10 | namespace OTransport.tests
11 | {
12 | [TestClass]
13 | public class ObjectTransport_TimeOut
14 | {
15 | [TestMethod]
16 | public void TimeOut_TimeOutFunctionSet_TimeOutFunctionCalled()
17 | {
18 | //Arrange
19 | var client = new Client("10.0.0.1",123);
20 | Client[] clientsWhoDidNotRespond = null;
21 | MockObjectMessage messageThatTimedOut = null;
22 |
23 | var sentPayload = string.Empty;
24 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
25 | .OnSendHandle((Client, payload) => sentPayload = payload);
26 |
27 | MockObjectMessage sendObject = new MockObjectMessage();
28 | sendObject.Property1_string = "Test String";
29 | sendObject.Property2_int = 12;
30 | sendObject.Property3_decimal = 1.33M;
31 |
32 | //Act
33 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
34 | networkChannel.SimulateClientConnect(client);
35 |
36 | transport.Send(sendObject)
37 | .Response(o => { })
38 | .SetTimeOut(1)
39 | .OnTimeOut(
40 | (c,o)=> {
41 | clientsWhoDidNotRespond = c;
42 | messageThatTimedOut = o;
43 | })
44 | .Execute();
45 |
46 | Utilities.WaitFor(ref clientsWhoDidNotRespond);
47 |
48 | //Assert
49 | Assert.AreEqual(1,clientsWhoDidNotRespond.Length);
50 | Assert.AreEqual(sendObject,messageThatTimedOut);
51 | }
52 |
53 | [TestMethod]
54 | public void TimeOut_MessageSentToMultipleClientsWithSomeResponding_TimeOutFunctionReturnsClientsWhoDidNotRespond()
55 | {
56 | //Arrange
57 | var client1 = new Client("10.0.0.1",123);
58 | var client2 = new Client("10.0.0.2",123);
59 | var client3 = new Client("10.0.0.3",123);
60 |
61 | Client[] clientsWhoDidNotRespond = null;
62 | MockObjectMessage messageThatTimedOut = null;
63 |
64 | var sentPayload = string.Empty;
65 | var networkChannel = MockNetworkChannelFactory.GetMockedNetworkChannel()
66 | .OnSendHandle((Client, payload) => sentPayload = payload);
67 |
68 | MockObjectMessage sendObject = new MockObjectMessage();
69 | sendObject.Property1_string = "Test String";
70 | sendObject.Property2_int = 12;
71 | sendObject.Property3_decimal = 1.33M;
72 |
73 | ObjectTransport transport = TestObjectTransportFactory.CreateNewObjectTransport(networkChannel);
74 | networkChannel.SimulateClientConnect(client1);
75 | networkChannel.SimulateClientConnect(client2);
76 | networkChannel.SimulateClientConnect(client3);
77 |
78 | //Act
79 | transport.Send(sendObject)
80 | .Response(o => { })
81 | .SetTimeOut(2)
82 | .OnTimeOut(
83 | (c,o)=> {
84 | clientsWhoDidNotRespond = c;
85 | messageThatTimedOut = o;
86 | })
87 | .ToAll()
88 | .Execute();
89 |
90 | //Echo back the message
91 | networkChannel.SimulateClientResponse(client2, sentPayload);
92 |
93 | Utilities.WaitFor(ref messageThatTimedOut);
94 |
95 | //Assert
96 | Assert.AreEqual(2,clientsWhoDidNotRespond.Length);
97 | Assert.IsTrue(clientsWhoDidNotRespond.Contains(client1));
98 | Assert.IsTrue(clientsWhoDidNotRespond.Contains(client3));
99 | Assert.AreEqual(sendObject,messageThatTimedOut);
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Serializer/Protobuf_MockObjectMessage.cs:
--------------------------------------------------------------------------------
1 | using ProtoBuf;
2 |
3 | namespace OTransport.tests
4 | {
5 | [ProtoContract]
6 | public class Protobuf_MockObjectMessage
7 | {
8 | [ProtoMember(1)]
9 | public string Property1_string { get; set; }
10 | [ProtoMember(2)]
11 | public int Property2_int { get; set; }
12 | [ProtoMember(3)]
13 | public decimal Property3_decimal { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Serializer/Protobuf_Serializer.tests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using OTransport;
3 | using OTransport.Serializer.protobuf;
4 | using OTransport.Test.Utilities;
5 | using OTransport.tests;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Text;
9 | using Test;
10 |
11 | namespace OTransport.Test.Serializer
12 | {
13 | [TestClass]
14 | public class Protobuf_Serializer
15 | {
16 | [TestMethod]
17 | public void Protobuff_UsingProtobuffSerializer_objectIsSentAndReceived()
18 | {
19 | //Arrange
20 | var joinedNetworkChannels = MockNetworkChannelFactory.GetConnectedChannels();
21 |
22 | Protobuf_MockObjectMessage sendMessage = new Protobuf_MockObjectMessage();
23 | sendMessage.Property1_string = "test send";
24 | sendMessage.Property2_int = 123;
25 | sendMessage.Property3_decimal = 56M;
26 |
27 | Protobuf_MockObjectMessage receivedMessage = null;
28 | Client receivedClient = null;
29 |
30 | //Act
31 | ObjectTransport client1 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item1,new ProtobufSerializer());
32 | client1.Receive((c, o) =>
33 | {
34 | receivedClient = c;
35 | receivedMessage = o;
36 | })
37 | .Execute();
38 |
39 |
40 | ObjectTransport client2 = TestObjectTransportFactory.CreateNewObjectTransport(joinedNetworkChannels.Item2,new ProtobufSerializer());
41 | client2.Send(sendMessage)
42 | .Execute();
43 |
44 | //Assert
45 | Assert.AreEqual(sendMessage.Property3_decimal, receivedMessage.Property3_decimal);
46 | Assert.AreEqual(sendMessage.Property1_string, receivedMessage.Property1_string);
47 | Assert.AreEqual(sendMessage.Property2_int, receivedMessage.Property2_int);
48 | Assert.AreEqual("10.0.0.2", receivedClient.IPAddress);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Utilities/MockNetworkChannelFactory.cs:
--------------------------------------------------------------------------------
1 | using Moq;
2 | using OTransport;
3 | using System;
4 | using System.Collections.Concurrent;
5 | using System.Collections.Generic;
6 | using System.Text;
7 |
8 | namespace Test
9 | {
10 | class MockNetworkChannelFactory
11 | {
12 | public static Tuple GetConnectedChannels()
13 | {
14 | var channel1 = new Mock();
15 | var channel2 = new Mock();
16 |
17 | Action channel1ReceiveFunction = null;
18 | Action channel2ReceiveFunction = null;
19 |
20 | var channel1Client = new Client("10.0.0.1", 123);
21 | var channel2Client = new Client("10.0.0.2", 321);
22 |
23 | Action channel1OnClient = null;
24 | Action channel2OnClient = null;
25 |
26 |
27 | channel1.Setup(c => c.Send(It.IsAny(), It.IsAny())).Callback((c, p) =>
28 | {
29 | ReceivedMessage message = new ReceivedMessage(channel1Client, p);
30 | channel2ReceiveFunction.Invoke(message);
31 | });
32 |
33 | channel1.Setup(c => c.OnReceive(It.IsAny>())).Callback>(
34 | function => channel1ReceiveFunction = function
35 | );
36 |
37 | channel2.Setup(c => c.Send(It.IsAny(), It.IsAny())).Callback((c, p) =>
38 | {
39 | ReceivedMessage message = new ReceivedMessage(channel2Client, p);
40 | channel1ReceiveFunction.Invoke(message);
41 | });
42 |
43 | channel2.Setup(c => c.OnReceive(It.IsAny>())).Callback>(
44 | function => channel2ReceiveFunction = function
45 | );
46 |
47 | channel2.Setup(c => c.OnClientConnect(It.IsAny>())).Callback>(a =>
48 | {
49 | channel2OnClient = a;
50 | channel2OnClient.Invoke(channel1Client);
51 | });
52 |
53 | channel1.Setup(c => c.OnClientConnect(It.IsAny>())).Callback>(a =>
54 | {
55 | channel1OnClient = a;
56 | channel1OnClient.Invoke(channel2Client);
57 | });
58 |
59 | Tuple channels = new Tuple(channel1.Object,channel2.Object);
60 |
61 | return channels;
62 | }
63 | public static MockedNetworkChannel GetMockedNetworkChannel()
64 | {
65 | MockedNetworkChannel mock = new MockedNetworkChannel();
66 | return mock;
67 | }
68 |
69 |
70 | }
71 | public class MockedNetworkChannel : INetworkChannel
72 | {
73 | private Action MockSendFunction = null;
74 |
75 | private Action ObjectTransportReceive = null;
76 | private Action ObjectTransportClientConnect = null;
77 |
78 | public int LocalPort => throw new NotImplementedException();
79 |
80 | public MockedNetworkChannel OnSendHandle(Action sendFunction)
81 | {
82 | MockSendFunction = sendFunction;
83 | return this;
84 | }
85 |
86 | public void SendUnreliable(Client client, string message)
87 | {
88 | }
89 |
90 | public void SimulateClientConnect(Client client)
91 | {
92 | ObjectTransportClientConnect.Invoke(client);
93 | }
94 |
95 | public void SimulateClientResponse(Client client,string message)
96 | {
97 | ReceivedMessage receivedMessage = new ReceivedMessage(client,message);
98 | ObjectTransportReceive.Invoke(receivedMessage);
99 | }
100 |
101 | public void Stop()
102 | {
103 |
104 | }
105 |
106 | public void SetReliable()
107 | {
108 | }
109 |
110 | public void SetUnreliable()
111 | {
112 | }
113 |
114 | public void OnClientConnect(Action callBack)
115 | {
116 | ObjectTransportClientConnect = callBack;
117 | }
118 |
119 | public void OnReceive(Action callBack)
120 | {
121 | ObjectTransportReceive = callBack;
122 | }
123 |
124 | public void OnClientDisconnect(Action callBack)
125 | {
126 | }
127 |
128 | public void Send(Client client, string payload)
129 | {
130 | if(MockSendFunction!=null)
131 | MockSendFunction.Invoke(client, payload);
132 | }
133 |
134 | public void DisconnectClient(params Client[] client)
135 | {
136 | throw new NotImplementedException();
137 | }
138 |
139 | public void Start(string ipaddress, int port)
140 | {
141 | throw new NotImplementedException();
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Utilities/MockObjectMessage.cs:
--------------------------------------------------------------------------------
1 | namespace OTransport.tests
2 | {
3 | public class MockObjectMessage
4 | {
5 | public string Property1_string { get; set; }
6 | public int Property2_int { get; set; }
7 | public decimal Property3_decimal { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Utilities/MockObjectMessageWithBinary.cs:
--------------------------------------------------------------------------------
1 | namespace OTransport.tests
2 | {
3 | public class MockObjectMessageWithBinary
4 | {
5 | public byte[] Property1_Bytes { get; set; }
6 | public string Property2_String { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Utilities/TestObjectTransportFactory.cs:
--------------------------------------------------------------------------------
1 | using OTransport.Serializer.JSON;
2 | using OTransport;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using OTransport.Serializer;
7 |
8 | namespace OTransport.Test.Utilities
9 | {
10 | public static class TestObjectTransportFactory
11 | {
12 | public static ObjectTransport CreateNewObjectTransport(INetworkChannel channel)
13 | {
14 | var jsonSerializer = new JSONserializer();
15 |
16 | return new ObjectTransport(channel, jsonSerializer);
17 | }
18 | public static ObjectTransport CreateNewObjectTransport(INetworkChannel channel,ISerializer serializer)
19 | {
20 | return new ObjectTransport(channel, serializer);
21 | }
22 |
23 | internal static ObjectTransport CreateNewObjectTransportTCPclient()
24 | {
25 | var tcpClient = new NetworkChannel.TCP.TCPClientChannel();
26 | var jsonSerializer = new JSONserializer();
27 |
28 | return new ObjectTransport(tcpClient, jsonSerializer);
29 | }
30 | internal static ObjectTransport CreateNewObjectTransportUDPclient()
31 | {
32 | var udpClient = new NetworkChannel.UDP.UDPClientChannel();
33 | var jsonSerializer = new JSONserializer();
34 |
35 | return new ObjectTransport(udpClient, jsonSerializer);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ObjectTransport.tests/Utilities/Utilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using OTransport.tests;
5 | using System.Threading;
6 |
7 | namespace Test
8 | {
9 | class Utilities
10 | {
11 | public static void WaitFor(ref string test)
12 | {
13 | while(test == string.Empty || test == null) { }
14 | }
15 |
16 | internal static void WaitFor(ref bool executed)
17 | {
18 | while(executed == false) { }
19 | }
20 |
21 | internal static void WaitFor(ref T Object)
22 | {
23 | while(Object == null) { }
24 | }
25 |
26 | internal static void Wait()
27 | {
28 | Thread.Sleep(10);
29 | }
30 |
31 | internal static void WaitFor(Func check)
32 | {
33 |
34 | while (!check.Invoke()) { }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/ObjectTransport/Client.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport
6 | {
7 | public class Client
8 | {
9 | internal Client()
10 | {
11 |
12 | }
13 | public Client(string ipaddress,int port)
14 | {
15 | IPAddress = ipaddress;
16 | Port = port;
17 | }
18 |
19 | public string IPAddress { get; internal set; }
20 | public int Port { get; internal set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ObjectTransport/Factory/ObjectTransportAssemblyLine.cs:
--------------------------------------------------------------------------------
1 | using OTransport.Serializer;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace OTransport.Factory
7 | {
8 | public class ObjectTransportAssemblyLine
9 | {
10 | private INetworkChannel NetworkChannel;
11 | private ISerializer Serializer;
12 | private bool Reliable = false;
13 |
14 | public void SetNetworkChannel(INetworkChannel networkChannel)
15 | {
16 | NetworkChannel = networkChannel;
17 | }
18 |
19 | ///
20 | /// Specify a custom serializer to be used when serilizing objects.
21 | ///
22 | ///
23 | ///
24 | public ObjectTransportAssemblyLine SetSerializer(ISerializer serializer)
25 | {
26 | Serializer = serializer;
27 | return this;
28 | }
29 |
30 | public void SetReliableTransport()
31 | {
32 | Reliable = true;
33 | }
34 | public void SetUnreliableTransport()
35 | {
36 | Reliable = false;
37 | }
38 |
39 | public IObjectTransport Build()
40 | {
41 | if (Serializer == null)
42 | throw new ObjectTransportException("Please specify a Serializer to use. If you haven't done so, please install a serializer from nuget or implement your own.");
43 |
44 | var objectTransport = new ObjectTransport(NetworkChannel, Serializer);
45 |
46 | if (Reliable)
47 | objectTransport.SetReliable();
48 | else
49 | objectTransport.SetUnreliable();
50 |
51 | return objectTransport;
52 | }
53 |
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ObjectTransport/Factory/ObjectTransportFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport
6 | {
7 | public class ObjectTransportFactory
8 | {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/ObjectTransport/IObjectTransport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace OTransport
5 | {
6 | public interface IObjectTransport
7 | {
8 | ///
9 | /// Disconnects the first client that is connected. This is best used when the current object transport is a client connected to a server.
10 | ///
11 | void DisconnectClient();
12 | ///
13 | /// Disconnects the given client. If this is a client connected to a server, only the server can be passed in. Call DisconnectClient() instead.
14 | ///
15 | ///
16 | void DisconnectClient(params Client[] client);
17 | ///
18 | /// This function will return a list of all clients that are currently connected.
19 | ///
20 | /// IEnumerable of connected clients
21 | IEnumerable GetConnectedClients();
22 | ///
23 | /// Set the function/lambda to be called when a client connects.
24 | ///
25 | /// The function/lambda to call when a client connects
26 | void OnClientConnect(Action onConnectFunction);
27 | ///
28 | /// Set the function/lambda to be called when a client disconnects
29 | ///
30 | /// The function/lambda to call when a client disconnects
31 | void OnClientDisconnect(Action onDisconnectFunction);
32 | ///
33 | /// Use this method to handle the event when receiving a message fails to be processed by object transport.
34 | /// The first parameter is the Received message. This contains the message body as a string and the client who sent the message.
35 | /// The Second parameter is the exception that was thrown to cause the receive to fail.
36 | ///
37 | void OnFailedReceive(Action onfail);
38 | ///
39 | /// Setup a listener to execute when an object is received of the given type. This will execute the given function/lambda and pass in the object that was received.
40 | ///
41 | /// The received object type to listen for and handle.
42 | /// The function/lambda to execute when an object of the specified type is received. This function will have the object passed in as a parameter.
43 | ///
44 | MessageReceive Receive();
45 | ///
46 | /// Setup a listener to execute when an object is received of the given type. This will execute the given function/lambda and pass in the object that was received as well as the client who sent the object.
47 | ///
48 | /// The received object type to listen for and handle.
49 | /// The function/lambda to execute when an object of the specified type is received. This function will have the object passed in as a parameter. It will also have the client passed in.
50 | ///
51 | MessageReceive Receive(Action obj);
52 | ///
53 | /// Setup a listener to execute when an object is received of the given type. This will execute the given function/lambda and pass in the object that was received.
54 | ///
55 | /// The received object type to listen for and handle.
56 | /// The function/lambda to execute when an object of the specified type is received. This function will have the object passed in as a parameter.
57 | ///
58 | MessageReceive Receive(Action function);
59 | ///
60 | /// Send an object through the network channel
61 | ///
62 | /// The type of the object being sent.
63 | /// The object to send.
64 | ///
65 | MessageSend Send(SendType obj);
66 | ///
67 | /// Make any subsequent messages default to reliable. The underlining network channel will throw an exception if it is not supported
68 | ///
69 | void SetReliable();
70 | ///
71 | /// Make any subsequent messages default to unreliable. The underlining network channel will throw an exception if it is not supported
72 | ///
73 | void SetUnreliable();
74 | ///
75 | /// Stop the underlying channel
76 | ///
77 | void Stop();
78 |
79 |
80 | ///
81 | /// Start the object transport. If this is a client, this will connect to the target IP and port.
82 | /// If this is a server, this will start a server on the given ip and port.
83 | ///
84 | ///
85 | ///
86 | IObjectTransport Start(string ipaddress, int port);
87 | }
88 | }
--------------------------------------------------------------------------------
/ObjectTransport/MessageReceive.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace OTransport
5 | {
6 | public class MessageReceive
7 | {
8 | ReceivedMessageHandle handle = new ReceivedMessageHandle();
9 | private ObjectTransport ObjectTransport;
10 |
11 | internal MessageReceive(Delegate actionReceived,ObjectTransport objectTransport)
12 | {
13 | handle.ReceiveAction = actionReceived;
14 | ObjectTransport = objectTransport;
15 | }
16 |
17 | internal MessageReceive(ObjectTransport objectTransport)
18 | {
19 | ObjectTransport = objectTransport;
20 | }
21 |
22 | ///
23 | /// After receiving an object, execute a function/lambda. What ever this function/lambda returns will be sent back to the client who sent the original message. The original object that was received is passed as a paramter to the function/lambda.
24 | ///
25 | /// the function/lambda to execute to get a reply object to send back.
26 | ///
27 | public MessageReceive Reply(Func replyFunction)
28 | {
29 | handle.ReplyFunction = replyFunction;
30 | return this;
31 | }
32 |
33 | ///
34 | /// After receiving an object, execute a function/lambda. What ever this function/lambda returns will be sent back to the client who sent the original message. The original object that was received as well as the client who sent the original object is passed as a paramter to the function/lambda.
35 | ///
36 | /// the function/lambda to execute to get a reply object to send back.
37 | ///
38 | public MessageReceive Reply(Func replyFunction)
39 | {
40 | handle.ReplyFunction = replyFunction;
41 | return this;
42 | }
43 |
44 | ///
45 | /// Execute and begin listening for objects of the given type to be received.
46 | ///
47 | public void Execute()
48 | {
49 | handle.RecieveType = typeof(ReceivedType);
50 | ObjectTransport.AddToListenerHandles(handle);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ObjectTransport/MessageResponseHandle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport
6 | {
7 | internal class MessageResponseHandle
8 | {
9 | public MessageResponseHandle(QueuedMessage sent)
10 | {
11 | sentMessage = sent;
12 | }
13 |
14 | public List ClientsToRespond = new List();
15 |
16 | public QueuedMessage sentMessage { get; set; }
17 | public int SecondsPassed { get; set; } = 0;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ObjectTransport/MessageSend.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace OTransport
6 | {
7 | public class MessageSend
8 | {
9 | private QueuedMessage message = new QueuedMessage();
10 | private ObjectTransport ObjectTransport;
11 |
12 | internal MessageSend(SendType sendObject,ObjectTransport objectTransport)
13 | {
14 | message.ObjectToSend = sendObject;
15 | message.sendTo = objectTransport.GetConnectedClients().ToArray();
16 | ObjectTransport = objectTransport;
17 | message.SendReliable = ObjectTransport.SendReliable;
18 | }
19 |
20 | ///
21 | /// After sending an object, wait for a response back. If the response is of the given object type, execute the given function/lambda. The received object is fed into the function/lambda.
22 | /// The client who the object was sent to must respond with the reply function
23 | ///
24 | /// The object type to handle
25 | /// the function/lambda to execute when an object of the given type is received
26 | ///
27 | public MessageSend Response(Action onResponseFunction)
28 | {
29 | message.resonseType_to_actionMatch.Add(typeof(ResponseType), onResponseFunction);
30 | return this;
31 | }
32 |
33 | ///
34 | /// When a response is expected after sending an object but the timeout has run out, a handler will execute. This function sets the timeout function/lambda.
35 | ///
36 | /// The function/lambda to execute. An array of Clients who did not respond and the object that was sent is passed as parameters.
37 | ///
38 | public MessageSend OnTimeOut(Action function)
39 | {
40 | message.TimeOutFunction = function;
41 | return this;
42 | }
43 |
44 | ///
45 | /// After sending an object, wait for a response back. If the response is of the given object type, execute the given function/lambda. The received object as well as the client who sent it is fed into the function/lambda.
46 | /// The client who the object was sent to must respond with the reply function
47 | ///
48 | /// The object type to handle
49 | /// the function/lambda to execute when an object of the given type is received
50 | ///
51 | public MessageSend Response(Action onResponseFunction)
52 | {
53 | message.resonseType_to_actionMatch.Add(typeof(ResponseType), onResponseFunction);
54 | return this;
55 | }
56 |
57 | ///
58 | /// If there has been no response for the given amount of time, stop listening for responses
59 | ///
60 | /// The number of seconds to wait for a response
61 | ///
62 | public MessageSend SetTimeOut(int seconds)
63 | {
64 | message.TimeOutInSeconds = seconds;
65 | return this;
66 | }
67 | ///
68 | /// The client to send the message to. This is not needed if the message is going to a Server.
69 | ///
70 | ///
71 | ///
72 | public MessageSend To(params Client[] client)
73 | {
74 | message.sendTo = client;
75 | return this;
76 | }
77 |
78 | ///
79 | /// Send the given object to the client and listen for any responses back from the client
80 | ///
81 | public void Execute()
82 | {
83 | ObjectTransport.Send(message);
84 | }
85 |
86 | ///
87 | /// Send the object to all clients.
88 | ///
89 | ///
90 | public MessageSend ToAll()
91 | {
92 | message.sendTo = ObjectTransport.GetConnectedClients().ToArray();
93 | return this;
94 | }
95 | ///
96 | /// Send the object to all clients except the given clients
97 | ///
98 | /// Clients to exclude
99 | ///
100 | public MessageSend ToAllExcept(params Client [] except)
101 | {
102 | message.sendTo = ObjectTransport.GetConnectedClients().Where(c => !except.Contains(c)).ToArray();
103 | return this;
104 | }
105 |
106 | ///
107 | /// Send the object reliably over the given network channel if it is supported. If it is not supported, the channel will throw an exception.
108 | ///
109 | ///
110 | public MessageSend Reliable()
111 | {
112 | message.SendReliable = true;
113 | return this;
114 | }
115 |
116 | ///
117 | /// Send the object unreliably over the given network channel if it is supported. If it is not supported, the channel will throw an exception.
118 | ///
119 | ///
120 | public MessageSend Unreliable()
121 | {
122 | message.SendReliable = false;
123 | return this;
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/ObjectTransport/Network Channels/INetworkChannel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport
6 | {
7 | public interface INetworkChannel
8 | {
9 | int LocalPort { get; }
10 | void Stop();
11 | void SetReliable();
12 | void SetUnreliable();
13 | void OnClientConnect(Action callBack);
14 | void OnReceive(Action callBack);
15 | void OnClientDisconnect(Action callBack);
16 | void Send(Client client, string payload);
17 | void DisconnectClient(params Client[] client);
18 | void Start(string ipaddress, int port);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ObjectTransport/ObjectTransport.cs:
--------------------------------------------------------------------------------
1 | using OTransport.Factory;
2 | using OTransport.Serializer;
3 | using System;
4 | using System.Collections.Concurrent;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Reflection;
8 | using System.Threading;
9 |
10 | namespace OTransport
11 | {
12 | public class ObjectTransport : IObjectTransport
13 | {
14 | public static ObjectTransportFactory Factory = new ObjectTransportFactory();
15 | List clients = new List();
16 | private readonly INetworkChannel NetworkChannel;
17 | private readonly ISerializer Serializer;
18 |
19 | private ConcurrentDictionary ResponseHandle = new ConcurrentDictionary();
20 | private ConcurrentDictionary ReceiveHandle = new ConcurrentDictionary();
21 | private Action OnClientConnectHandler = null;
22 | private Action onClientDisconnectHandler = null;
23 | private Action OnFailedReceiveHandler = null;
24 |
25 | internal bool SendReliable = true;
26 | private readonly int TokenLength = 8;
27 |
28 | public ObjectTransport(INetworkChannel networkChannel, ISerializer serializer)
29 | {
30 | NetworkChannel = networkChannel;
31 | Serializer = serializer;
32 |
33 | TimeOutCheck();
34 | SetupNetworkReceiveCallback();
35 | SetUpClientConnectCallback();
36 | }
37 |
38 | ///
39 | /// Make any subsequent messages default to reliable. The underlining network channel will throw an exception if it is not supported
40 | ///
41 | public void SetReliable()
42 | {
43 | SendReliable = true;
44 | }
45 |
46 | ///
47 | /// Make any subsequent messages default to unreliable. The underlining network channel will throw an exception if it is not supported
48 | ///
49 | public void SetUnreliable()
50 | {
51 | SendReliable = false;
52 | }
53 | ///
54 | /// This function will return a list of all clients that are currently connected.
55 | ///
56 | /// IEnumerable of connected clients
57 | public IEnumerable GetConnectedClients()
58 | {
59 | return clients;
60 | }
61 |
62 | ///
63 | /// Set the function/lambda to be called when a client connects.
64 | ///
65 | /// The function/lambda to call when a client connects
66 | public void OnClientConnect(Action onConnectFunction)
67 | {
68 | OnClientConnectHandler = onConnectFunction;
69 | }
70 | ///
71 | /// Set the function/lambda to be called when a client disconnects
72 | ///
73 | /// The function/lambda to call when a client disconnects
74 | public void OnClientDisconnect(Action onDisconnectFunction)
75 | {
76 | onClientDisconnectHandler = onDisconnectFunction;
77 | }
78 |
79 | private void TimeOutCheck()
80 | {
81 | Timer timer = new Timer(o =>
82 | {
83 | IEnumerable keys = ResponseHandle.Keys;
84 | foreach(var key in keys)
85 | {
86 | MessageResponseHandle handler;
87 | while(!ResponseHandle.TryGetValue(key, out handler)){ }
88 |
89 | if (handler == null)
90 | continue;
91 |
92 | handler.SecondsPassed += 1;
93 |
94 | if(handler.SecondsPassed >= handler.sentMessage.TimeOutInSeconds)
95 | {
96 | while (!ResponseHandle.TryRemove(key,out handler)) { }
97 |
98 | if (handler.sentMessage.TimeOutFunction != null)
99 | handler.sentMessage.TimeOutFunction.DynamicInvoke(handler.ClientsToRespond.ToArray(), handler.sentMessage.ObjectToSend);
100 | }
101 |
102 | }
103 |
104 | }, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
105 | }
106 |
107 | private void SetupNetworkReceiveCallback()
108 | {
109 | //Set a callback for the network channel
110 |
111 | NetworkChannel.OnReceive((message) =>
112 | {
113 | try
114 | {
115 | (Type, string, string) objectType_token_objectPayload = ParseRecievedMessage(message.Message);
116 |
117 | Type receivedObjectType = objectType_token_objectPayload.Item1;
118 | string token = objectType_token_objectPayload.Item2;
119 | string objectPayload = objectType_token_objectPayload.Item3;
120 |
121 | if (receivedObjectType == null)
122 | return;
123 |
124 | object receivedObject = Serializer.Deserialize(objectPayload, receivedObjectType);
125 |
126 | if (token != null && ResponseHandle.ContainsKey(token))
127 | {
128 | CheckExecuteResponseHandle(message, receivedObjectType, token, receivedObject);
129 | }
130 | else if (ReceiveHandle.ContainsKey(receivedObjectType))
131 | {
132 | CheckExecuteReceiveAction(message, receivedObjectType, receivedObject);
133 | CheckExecuteReplyAction(message, receivedObjectType, token, receivedObject);
134 | }
135 | }
136 | catch(Exception e)
137 | {
138 | //Error parsing the message. Invoke the OnFailedReceiveHandler.
139 | OnFailedReceiveHandler?.Invoke(message, e);
140 | return;
141 | }
142 | });
143 | }
144 |
145 | ///
146 | /// Use this method to handle the event when receiving a message fails to be processed by object transport.
147 | /// The first parameter is the Received message. This contains the message body as a string and the client who sent the message.
148 | /// The Second parameter is the exception that was thrown to cause the receive to fail.
149 | ///
150 | public void OnFailedReceive(Action onfail)
151 | {
152 | OnFailedReceiveHandler = onfail;
153 | }
154 |
155 | ///
156 | /// Disconnects the given client. If this is a client connected to a server, only the server can be passed in. Call DisconnectClient() instead.
157 | ///
158 | ///
159 | public void DisconnectClient(params Client[] client)
160 | {
161 | NetworkChannel.DisconnectClient(client);
162 | }
163 | ///
164 | /// Disconnects the first client that is connected. This is best used when the current object transport is a client connected to a server.
165 | ///
166 | public void DisconnectClient()
167 | {
168 |
169 | if (this.clients.Count() > 0)
170 | {
171 | NetworkChannel.DisconnectClient(this.clients.First());
172 | }
173 | }
174 |
175 | private (Type, string, string) ParseRecievedMessage(string message)
176 | {
177 | int firstDivide = message.IndexOf("::");
178 | var typeName = message.Substring(0, firstDivide);
179 |
180 | Type returnType = Type.GetType(typeName);
181 | var payload = message.Substring(firstDivide + 2);
182 | string token = null;
183 |
184 | int secondDivide = payload.IndexOf("::");
185 |
186 | if(secondDivide > -1 && secondDivide == TokenLength)
187 | {
188 | token = payload.Substring(0, secondDivide);
189 | payload = payload.Substring(secondDivide + 2);
190 | }
191 |
192 | return (returnType,token,payload);
193 | }
194 |
195 | private void CheckExecuteResponseHandle(ReceivedMessage message, Type receivedObjectType, string token, object receivedObject)
196 | {
197 | var responseType_ActionMatch = ResponseHandle[token].sentMessage.resonseType_to_actionMatch;
198 | if (responseType_ActionMatch.ContainsKey(receivedObjectType))
199 | {
200 | Delegate responseHandle = responseType_ActionMatch[receivedObjectType];
201 | if (responseHandle.GetMethodInfo().GetParameters().Count() > 1)
202 | {
203 | responseHandle.DynamicInvoke(message.From, receivedObject);
204 | }
205 | else
206 | {
207 | responseHandle.DynamicInvoke(receivedObject);
208 | }
209 |
210 | //Remove the client from the list of clients who still need to respond
211 | ResponseHandle[token].ClientsToRespond.Remove(message.From);
212 | }
213 | }
214 |
215 | private void CheckExecuteReceiveAction(ReceivedMessage message,Type receivedObjectType, object receivedObject)
216 | {
217 | Delegate receiveAction = ReceiveHandle[receivedObjectType].ReceiveAction;
218 | if (receiveAction != null)
219 | {
220 | if (receiveAction.GetMethodInfo().GetParameters().Count() > 1)
221 | {
222 | receiveAction.DynamicInvoke(message.From, receivedObject);
223 | }
224 | else
225 | {
226 | receiveAction.DynamicInvoke(receivedObject);
227 | }
228 |
229 | }
230 | }
231 |
232 | private void CheckExecuteReplyAction(ReceivedMessage message, Type receivedObjectType, string token, object receivedObject)
233 | {
234 | Delegate replyFunction = ReceiveHandle[receivedObjectType].ReplyFunction;
235 | if (replyFunction != null)
236 | {
237 | object result;
238 | if (replyFunction.GetMethodInfo().GetParameters().Count() > 1)
239 | result = replyFunction.DynamicInvoke(message.From, receivedObject);
240 | else
241 | result = replyFunction.DynamicInvoke(receivedObject);
242 |
243 | if (result == null)
244 | return;
245 |
246 | QueuedMessage queueMessage = new QueuedMessage();
247 | queueMessage.ObjectToSend = result;
248 | queueMessage.sendTo = new Client[] { message.From };
249 | queueMessage.SendReliable = SendReliable;
250 | queueMessage.Token = token;
251 | Send(queueMessage);
252 | }
253 | }
254 |
255 | private void SetUpClientConnectCallback()
256 | {
257 | NetworkChannel.OnClientConnect((client)=>
258 | {
259 | clients.Add(client);
260 | OnClientConnectHandler?.Invoke(client);
261 | });
262 |
263 | NetworkChannel.OnClientDisconnect((client)=>
264 | {
265 | clients.Remove(client);
266 | onClientDisconnectHandler?.Invoke(client);
267 | });
268 | }
269 |
270 | private string GenerateToken()
271 | {
272 | //Get the first 8 characters of a newly generated token
273 | return Guid.NewGuid().ToString().Split('-')[0];
274 | }
275 | private string GetPayload(QueuedMessage send)
276 | {
277 | object objectToSend = send.ObjectToSend;
278 | Type objectType = objectToSend.GetType();
279 |
280 | string object_AssemblyQualifiedName = objectType.AssemblyQualifiedName;
281 | string serialized_object = Serializer.Serialize(objectToSend);
282 |
283 | string token = send.Token;
284 |
285 | //If this queued message is waiting for a response eg (Send().Response())
286 | if (send.resonseType_to_actionMatch.Count > 0)
287 | {
288 | token = GenerateToken();
289 |
290 | MessageResponseHandle responseHandle = new MessageResponseHandle(send);
291 | responseHandle.ClientsToRespond.AddRange(send.sendTo);
292 | ResponseHandle.TryAdd(token, responseHandle);
293 | }
294 |
295 | string payload = string.Empty;
296 |
297 | if(token == null)
298 | payload = string.Format("{0}::{1}", object_AssemblyQualifiedName, serialized_object);
299 | else
300 | payload = string.Format("{0}::{1}::{2}", object_AssemblyQualifiedName, token, serialized_object);
301 |
302 | return payload;
303 | }
304 | internal void Send(QueuedMessage send)
305 | {
306 | if (clients.Count == 0)
307 | return;
308 |
309 | Client[] clientsTo = send.sendTo;
310 |
311 | send.sendTo = clientsTo;
312 |
313 | string payload = GetPayload(send);
314 |
315 | foreach (Client client in clientsTo)
316 | {
317 | if (send.SendReliable)
318 | NetworkChannel.SetReliable();
319 | else
320 | NetworkChannel.SetUnreliable();
321 |
322 | NetworkChannel.Send(client, payload);
323 | }
324 | }
325 | ///
326 | /// Stop the underlying channel
327 | ///
328 | public void Stop()
329 | {
330 | NetworkChannel.Stop();
331 | }
332 |
333 | ///
334 | /// Send an object through the network channel
335 | ///
336 | /// The type of the object being sent.
337 | /// The object to send.
338 | ///
339 | public MessageSend Send(SendType obj)
340 | {
341 | var messageSend = new MessageSend(obj,this);
342 |
343 | return messageSend;
344 | }
345 | internal void AddToListenerHandles(ReceivedMessageHandle handle)
346 | {
347 | Type type = handle.RecieveType;
348 | if (ReceiveHandle.ContainsKey(type))
349 | throw new ObjectTransportException("This object type is already being handled");
350 |
351 | while(!ReceiveHandle.TryAdd(type, handle)) { }
352 | }
353 | ///
354 | /// Setup a listener to execute when an object is received of the given type. This will execute the given function/lambda and pass in the object that was received.
355 | ///
356 | /// The received object type to listen for and handle.
357 | /// The function/lambda to execute when an object of the specified type is received. This function will have the object passed in as a parameter.
358 | ///
359 | public MessageReceive Receive(Action function)
360 | {
361 | return new MessageReceive(function,this);
362 | }
363 |
364 | ///
365 | /// Setup a listener to execute when an object is received of the given type. This will execute the given function/lambda and pass in the object that was received as well as the client who sent the object.
366 | ///
367 | /// The received object type to listen for and handle.
368 | /// The function/lambda to execute when an object of the specified type is received. This function will have the object passed in as a parameter. It will also have the client passed in.
369 | ///
370 | public MessageReceive Receive(Action obj)
371 | {
372 | return new MessageReceive(obj,this);
373 | }
374 | ///
375 | /// Setup a listener to execute when an object is received of the given type.
376 | ///
377 | /// The received object type to listen for and handle.
378 | ///
379 | public MessageReceive Receive()
380 | {
381 | return new MessageReceive(this);
382 | }
383 |
384 | public IObjectTransport Start(string ipaddress, int port)
385 | {
386 | NetworkChannel.Start(ipaddress, port);
387 | return this;
388 | }
389 | }
390 | }
391 |
--------------------------------------------------------------------------------
/ObjectTransport/ObjectTransport.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PackageReference
5 | netstandard1.6;netcoreapp1.1;net46
6 | OTransport
7 | ObjectTransport
8 | 1.1.3
9 | Rhyno van der Sluijs
10 |
11 | A simple lightweight library that allows you to send and receive Objects over TCP or UDP. This assembly contains the project interfaces as well as abstract implementations. You must install the implementations to use this framework.
12 | Please see the following link for more information about installing ObjectTransport:
13 | https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
14 |
15 | false
16 |
17 | This release introduces the DisconnectClient function which allows you to disconnect a connected client.
18 |
19 |
20 | TCP Server Object networking UDP
21 | https://github.com/RhynoVDS/ObjectTransport
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | true
43 | true
44 | Content
45 | true
46 | Always
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/ObjectTransport/ObjectTransportException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace OTransport
4 | {
5 | public class ObjectTransportException : Exception
6 | {
7 | public ObjectTransportException()
8 | {
9 | }
10 |
11 | public ObjectTransportException(string message) : base(message)
12 | {
13 | }
14 |
15 | public ObjectTransportException(string message, Exception innerException) : base(message, innerException)
16 | {
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/ObjectTransport/PayLoad/QueuedMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace OTransport
6 | {
7 | internal class QueuedMessage
8 | {
9 | public Dictionary resonseType_to_actionMatch { get; set; } = new Dictionary();
10 | public int TimeOutInSeconds { get; set; } = 15;
11 | public object ObjectToSend { get; set; }
12 | public string Token { get; set; }
13 | public Client[] sendTo { get; set; }
14 | public Delegate TimeOutFunction { get; set; }
15 |
16 | public bool SendReliable { get; set; }
17 |
18 | }
19 | }
--------------------------------------------------------------------------------
/ObjectTransport/PayLoad/ReceivedConnection.cs:
--------------------------------------------------------------------------------
1 | namespace OTransport
2 | {
3 | public class ReceivedConnection
4 | {
5 | public string Address { get; set; }
6 | public int Port { get; set; }
7 |
8 | public ReceivedConnection(string address,int port)
9 | {
10 | Address = address;
11 | Port = port;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/ObjectTransport/PayLoad/ReceivedMessage.cs:
--------------------------------------------------------------------------------
1 | namespace OTransport
2 | {
3 | public class ReceivedMessage
4 | {
5 | public Client From { get; }
6 | public string Message { get; }
7 |
8 | public ReceivedMessage(Client client, string message)
9 | {
10 | From = client;
11 | Message = message;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/ObjectTransport/ReceivedMessageHandle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport
6 | {
7 | class ReceivedMessageHandle
8 | {
9 | public Type RecieveType { get; set; }
10 | public Delegate ReceiveAction { get; set; }
11 | public Delegate ReplyFunction { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ObjectTransport/Serializer/ISerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace OTransport.Serializer
6 | {
7 | public interface ISerializer
8 | {
9 | string Serialize(object obj);
10 | object Deserialize(string objectPayload, Type objectType);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # ObjectTransport
4 |
5 | A lightweight library that allows you to send and receive objects over TCP or UDP. ObjectTranport aims to be a network framework that is as simple and lightweight as possible.
6 |
7 | Multiple serialization options are available such as Protobuf. Serialization is injectable and you can implement your own.
8 |
9 | ## Install
10 |
11 | ObjectTransport is split into seperate packages based off your needs and available on nuget. Plese see installation instructions for more details:
12 | https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
13 |
14 | ## Simple Example
15 |
16 | ### Starting the server
17 |
18 | You can start a TCP server with the following code:
19 |
20 | ```csharp
21 |
22 | var server = ObjectTransport.Factory.CreateTCPServer()
23 | .UseJSONserialization();
24 | .Build();
25 |
26 | //Start the TCP server on port 123
27 | server.Start("127.0.0.1",123);
28 | ```
29 |
30 | or you can start a UDP server
31 |
32 | ```csharp
33 | var server = ObjectTransport.Factory.CreateUDPServer()
34 | .UseJSONserialization();
35 | .Build();
36 |
37 | //Start the UDP server on port 123
38 | server.Start("127.0.0.1",123);
39 |
40 | ```
41 |
42 | ### Receiving an Object
43 |
44 | In this example we have a scenario where we want to handle a user logging into the server. Suppose we have a simple class called "LoginModel". For now this class only has the field "Username"
45 |
46 | ```csharp
47 | public class LoginModel
48 | {
49 | public string Username {get;set;}
50 | }
51 | ```
52 |
53 | We want the server to receive this object and handle it. This can be done using the "Receive" function:
54 |
55 | ```csharp
56 | server.Receive(lm =>
57 | {
58 | Console.WriteLine(lm.Username);
59 | })
60 | .Execute();
61 | ```
62 |
63 | In the above code, we specify that when the server Receives an object of type "LoginModel", execute the given lambda. We then write the Username to the console.
64 |
65 | It is possible to set up multiple Receive functions and handle other types:
66 |
67 | ```csharp
68 | server.Receive(lm => ... ).Execute();
69 |
70 | server.Receive(lm => ... ).Execute();
71 |
72 | server.Receive(lm => ... ).Execute();
73 | ...
74 | ```
75 |
76 | ### Starting the client
77 |
78 | You can start a TCP client with the following code:
79 |
80 | ```csharp
81 | var client = ObjectTransport.Factory.CreateTCPClient()
82 | .UseJSONserialization();
83 | .Build();
84 |
85 | //Start the client and connect to the target IP address and port
86 | client.Start("10.0.0.1",123);
87 | ```
88 |
89 | To send an object over the channel, use the "Send" function:
90 |
91 | ```csharp
92 | var loginRequest = new LoginModel()
93 | loginRequest.Username = "TestUser";
94 |
95 | client.Send(loginRequest).Execute();
96 | ```
97 |
98 | ## Setting up multiple responses
99 |
100 | In the following example, we will show how a server/client can reply to a received object.
101 |
102 | In our previous example, we are currently sending a Username to the server but not our password, which isn't very secure. In this example, we update our model to have a "Password" field:
103 |
104 | ```csharp
105 | public class LoginModel
106 | {
107 | public string Username {get;set;}
108 | public string Password {get;set;}
109 | }
110 | ```
111 |
112 | ### Sending Login Request from the client
113 |
114 | Our client needs to send a login request to the server and will now need to send their password as well. Due to this, we want to handle any responses to our request including whether or not the login was successful. To handle this, we create two new classes "LoginSuccess" and "LoginFailure".
115 |
116 | ```csharp
117 | public class LoginSuccess
118 | {
119 | public string Name {get;set;}
120 | public string Password {get;set;}
121 | }
122 |
123 | public class LoginFailure
124 | {
125 | public string Message {get;set;}
126 | }
127 | ```
128 |
129 |
130 | In our client code, we will now use the "Response" function after sending the login object. When the server replies to the object that was sent, the client will handle it's responses:
131 |
132 | ```csharp
133 | var transport = ObjectTransport.Factory.CreateTCPClient("10.0.0.1",123);
134 |
135 | var loginRequest = new LoginModel();
136 | loginRequest.Username = "TestUser";
137 | loginRequest.Password = "A password";
138 |
139 | transport.Send(loginRequest)
140 | .Response(ls=>{
141 | Console.WriteLine("Welcome Back {0}", ls.Name);
142 | })
143 | .Response(lr=>{
144 | Console.WriteLine(lr.Message)
145 | })
146 | .Execute();
147 |
148 | ```
149 | In the above example, we setup 2 response handles, one to handle "LoginSuccess" and another to handle "LoginFailure".
150 |
151 | On the server, we will use the "Reply" function after receiving a login model. When using this function we need use a function/lambda which will "return" an object that will be sent back:
152 |
153 | ```csharp
154 |
155 | server.Receive()
156 | .Reply(lr=> {
157 |
158 | string user = string.empty;
159 | //Check if login is valid
160 |
161 | if(utilities.Login(lr, out user))
162 | {
163 |
164 | //Return an object back to the client
165 |
166 | var response = new LoginSuccess();
167 | response.Message = "Login Successful";
168 | response.Name = user;
169 |
170 | return response;
171 | }
172 | else
173 | {
174 |
175 | //Return an object back to the client
176 |
177 | var response = new LoginFailure();
178 | response.Message = "Login Failed";
179 |
180 | return response;
181 | }
182 | })
183 | .Execute();
184 |
185 | ```
186 |
187 | ## Specifying client to send to
188 |
189 | When multiple clients are connected, it is possible to specify which client to send a message to using the "To" function. You can specify multiple clients in the "To" function.
190 |
191 | ```csharp
192 | server.Send(anObjectToSend)
193 | .To(client1,client2, ... ClientN)
194 | .Execute();
195 | ```
196 | ### Send to all clients
197 |
198 | You can send to all clients using the following.
199 |
200 | ```csharp
201 |
202 | //Send to all clients
203 | server.Send(anObjectToSend)
204 | .ToAll()
205 | .Execute();
206 |
207 | //Note that you don't actually need to specify ToAll anymore. By default the API will send to all
208 |
209 | ```
210 |
211 | ### Send to all clients except given clients
212 | You can also send to all clients and specify who to exclude:
213 |
214 | ```csharp
215 |
216 | //Send to all clients except client 3
217 | server.Send(anObjectToSend)
218 | .ToAllExcept(client3) //Can exclude more eg: .ToAllExcept(client3,client2, ... clientN)
219 | .Execute();
220 |
221 | ```
222 |
223 | ## OnConnect / OnDisconnet handles
224 |
225 | You can specify what should happen when someone connects or disconnects:
226 |
227 | ```csharp
228 |
229 | //Setup onconnect handler
230 | transport.OnClientConnect(c => Console.WriteLine("A client has connected with ip {0}",c.IPAddress));
231 |
232 | //Setup onDisconnect handler
233 | transport.OnClientDisconnect(c=> Console.WriteLine("A client has disconnected with ip {0}",c.IPAddress));
234 |
235 | ```
236 |
237 | ## Sending object reliably
238 |
239 | When sending objects over UDP, the message is sent without reliability. You can switch reliably on for UDP on with the following:
240 |
241 | ```csharp
242 | client.SetReliable();
243 | ```
244 |
245 | After executing the above line, all objects that are sent will be sent reliably.
246 |
247 | Another option is to send only a specific message reliably. The following demonstrates this:
248 |
249 | ```csharp
250 |
251 | client.Send(anObjectToSend)
252 | .Reliable();
253 | .Execute();
254 | ```
255 |
256 | ## Disconnect Client
257 |
258 | To disconnect one ore more clients from the server, you can use the DisconnectClient function:
259 |
260 | ```csharp
261 |
262 | server.DisconnectClient(client1,client2, ... clientN);
263 |
264 | ```
265 |
--------------------------------------------------------------------------------