THRIFT-4039 Update of Apache Thrift .Net Core lib
Client: NetCore
Patch: Volodymyr Gotra <vgotra@gmail.com>
This closes #1163
Changes:
- Added framed transport, updated docs, updated global.json with SDKversion
- Added usage to multiplexer to tutorial
- Changed sdk to current sdk 1.0.0-preview2-1-003177
diff --git a/lib/netcore/README.md b/lib/netcore/README.md
index ae926e9..a2b19a8 100644
--- a/lib/netcore/README.md
+++ b/lib/netcore/README.md
@@ -2,20 +2,34 @@
Thrift client library ported to Microsoft .Net Core
+# Content
+- Tests/Thrift.PublicInterfaces.Compile.Tests - project for checking public interfaces during adding changes to Thrift library
+- Thrift - Thrift library
+
+# Reused components
+- NET Core Standard 1.6 (SDK 1.0.0-preview2-003121)
+- NET Core App 1.1
+
# How to build
-* Download the latest version of dotnet from https://www.microsoft.com/net/core (it can be https://go.microsoft.com/fwlink/?LinkID=809122 in case of VS Code)
-* Install downloaded version of dotnet
-* Clone repo
-* Run **build.sh** or **build.cmd** from the root of cloned repository
-* Check tests in **src/Tests** folder
-* Continue with /tutorials/netcore
+- Download and install .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015
+- Ensure that you have thrift.exe which supports netcore lib and it added to PATH
+- Go to current folder
+- Run **build.sh** or **build.cmd** from the root of cloned repository
+- Check tests in **src/Tests** folder
+- Continue with /tutorials/netcore
#Notes
-* No Silverlight suport, no longer supported by Microsoft
+- Migration to .NET Standard 2.0 planned for later (Q1 2017) according to https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/
+- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Haat Linux, OpenSuse, etc.)
#Known issues
-* Framed transport not fully implemenented yet
+- In trace logging mode you can see some not important internal exceptions
+- Ubuntu 16.10 still not supported fully
+- There is some problems with .NET Core CLI and usage specific -r|--runtime for building and publishing projects with different target frameworks (netstandard1.6 and netcoreapp1.1)
+# Troubleshouting
+
+It's possible to change dotnet SDK version for building for solution (in **global.json**). Just run **dotnet --info** to check your current version (or check your dotnet sdk folder for installed versions)
\ No newline at end of file
diff --git a/lib/netcore/Thrift/TBaseClient.cs b/lib/netcore/Thrift/TBaseClient.cs
index 24e08ce..5b338c6 100644
--- a/lib/netcore/Thrift/TBaseClient.cs
+++ b/lib/netcore/Thrift/TBaseClient.cs
@@ -35,6 +35,7 @@
private readonly TProtocol _outputProtocol;
private bool _isDisposed;
private int _seqId;
+ public readonly Guid ClientId = Guid.NewGuid();
protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol)
{
diff --git a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
index 514c1a6..f54a42a 100644
--- a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
@@ -37,8 +37,6 @@
public TFramedClientTransport(TClientTransport transport)
{
- throw new NotImplementedException("TFramedClientTransport is not fully ready for usage");
-
if (transport == null)
{
throw new ArgumentNullException(nameof(transport));
diff --git a/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs b/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs
new file mode 100644
index 0000000..0b86e9e
--- /dev/null
+++ b/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs
@@ -0,0 +1,150 @@
+// Licensed to the Apache Software Foundation(ASF) under one
+// or more contributor license agreements.See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+using Thrift.Transports.Client;
+
+namespace Thrift.Transports.Server
+{
+ // ReSharper disable once InconsistentNaming
+ public class TServerFramedTransport : TServerTransport
+ {
+ private readonly int _clientTimeout;
+ private readonly int _port;
+ private TcpListener _server;
+
+ public TServerFramedTransport(TcpListener listener)
+ : this(listener, 0)
+ {
+ }
+
+ public TServerFramedTransport(TcpListener listener, int clientTimeout)
+ {
+ _server = listener;
+ _clientTimeout = clientTimeout;
+ }
+
+ public TServerFramedTransport(int port)
+ : this(port, 0)
+ {
+ }
+
+ public TServerFramedTransport(int port, int clientTimeout)
+ {
+ _port = port;
+ _clientTimeout = clientTimeout;
+ try
+ {
+ // Make server socket
+ _server = new TcpListener(IPAddress.Any, _port);
+ _server.Server.NoDelay = true;
+ }
+ catch (Exception)
+ {
+ _server = null;
+ throw new TTransportException("Could not create ServerSocket on port " + port + ".");
+ }
+ }
+
+ public override void Listen()
+ {
+ // Make sure not to block on accept
+ if (_server != null)
+ {
+ try
+ {
+ _server.Start();
+ }
+ catch (SocketException sx)
+ {
+ throw new TTransportException("Could not accept on listening socket: " + sx.Message);
+ }
+ }
+ }
+
+ public override bool IsClientPending()
+ {
+ return _server.Pending();
+ }
+
+ protected override async Task<TClientTransport> AcceptImplementationAsync(CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return await Task.FromCanceled<TClientTransport>(cancellationToken);
+ }
+
+ if (_server == null)
+ {
+ throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
+ }
+
+ try
+ {
+ TFramedClientTransport tSocketTransport = null;
+ var tcpClient = await _server.AcceptTcpClientAsync();
+
+ try
+ {
+ tSocketTransport = new TFramedClientTransport(new TSocketClientTransport(tcpClient)
+ {
+ Timeout = _clientTimeout
+ });
+
+ return tSocketTransport;
+ }
+ catch (Exception)
+ {
+ if (tSocketTransport != null)
+ {
+ tSocketTransport.Dispose();
+ }
+ else // Otherwise, clean it up ourselves.
+ {
+ ((IDisposable) tcpClient).Dispose();
+ }
+
+ throw;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new TTransportException(ex.ToString());
+ }
+ }
+
+ public override void Close()
+ {
+ if (_server != null)
+ {
+ try
+ {
+ _server.Stop();
+ }
+ catch (Exception ex)
+ {
+ throw new TTransportException("WARNING: Could not close server socket: " + ex);
+ }
+ _server = null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/netcore/global.json b/lib/netcore/global.json
index 8c09275..e516241 100644
--- a/lib/netcore/global.json
+++ b/lib/netcore/global.json
@@ -1,3 +1,6 @@
{
- "projects": [ "." ]
+ "projects": [ "." ],
+ "sdk": {
+ "version": "1.0.0-preview2-1-003177" // "1.0.0-preview2-003121", "1.0.0-preview4-004233"
+ }
}
\ No newline at end of file
diff --git a/test/netcore/README.md b/test/netcore/README.md
new file mode 100644
index 0000000..230897f
--- /dev/null
+++ b/test/netcore/README.md
@@ -0,0 +1,17 @@
+# Apache Thrift net-core-lib tests
+
+Tests for Thrift client library ported to Microsoft .Net Core
+
+# Content
+- ThriftTest - tests for Thrift library
+
+# Reused components
+- NET Core Standard 1.6 (SDK 1.0.0-preview2-003121)
+- NET Core App 1.1
+
+# How to build
+- Download and install .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md)
+- Ensure that you have thrift.exe which supports netcore lib and it added to PATH
+- Go to current folder
+- Run **build.sh** or **build.cmd** from the root of cloned repository
+
diff --git a/test/netcore/global.json b/test/netcore/global.json
index 53f1811..42ed97a 100644
--- a/test/netcore/global.json
+++ b/test/netcore/global.json
@@ -1,3 +1,6 @@
{
- "projects": [ "../../lib/netcore" ]
+ "projects": [ "../../lib/netcore" ],
+ "sdk": {
+ "version": "1.0.0-preview2-1-003177" // "1.0.0-preview2-003121", "1.0.0-preview4-004233"
+ }
}
\ No newline at end of file
diff --git a/tutorial/netcore/Client/Program.cs b/tutorial/netcore/Client/Program.cs
index 5485e95..ae1837b 100644
--- a/tutorial/netcore/Client/Program.cs
+++ b/tutorial/netcore/Client/Program.cs
@@ -36,17 +36,17 @@
{
public class Program
{
- private static readonly ILogger Logger = new LoggerFactory().CreateLogger(nameof(Client));
+ private static readonly ILogger Logger = new LoggerFactory().AddConsole().AddDebug().CreateLogger(nameof(Client));
private static void DisplayHelp()
{
- Console.WriteLine(@"
+ Logger.LogInformation(@"
Usage:
Client.exe -h
will diplay help information
- Client.exe -t:<transport> -p:<protocol>
- will run client with specified arguments (tcp transport and binary protocol by default)
+ Client.exe -t:<transport> -p:<protocol> -mc:<numClients>
+ will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client
Options:
-t (transport):
@@ -55,11 +55,16 @@
namedpipe - namedpipe transport will be used (pipe address - "".test"")
http - http transport will be used (address - ""http://localhost:9090"")
tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090)
+ framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
-p (protocol):
binary - (default) binary protocol will be used
compact - compact protocol will be used
json - json protocol will be used
+ multiplexed - multiplexed protocol will be used
+
+ -mc (multiple clients):
+ <numClients> - number of multiple clients to connect to server (max 100, default 1)
Sample:
Client.exe -t:tcp -p:binary
@@ -76,6 +81,7 @@
return;
}
+ Logger.LogInformation("Starting client...");
using (var source = new CancellationTokenSource())
{
@@ -85,15 +91,38 @@
private static async Task RunAsync(string[] args, CancellationToken cancellationToken)
{
- var clientTransport = GetTransport(args);
+ var numClients = GetNumberOfClients(args);
- Logger.LogInformation($"Selected client transport: {clientTransport}");
+ Logger.LogInformation($"Selected # of clients: {numClients}");
- var clientProtocol = GetProtocol(args, clientTransport);
+ var transports = new TClientTransport[numClients];
+ for (int i = 0; i < numClients; i++)
+ {
+ var t = GetTransport(args);
+ transports[i] = t;
+ }
+
+ Logger.LogInformation($"Selected client transport: {transports[0]}");
- Logger.LogInformation($"Selected client protocol: {clientProtocol}");
+ var protocols = new Tuple<Protocol, TProtocol>[numClients];
+ for (int i = 0; i < numClients; i++)
+ {
+ var p = GetProtocol(args, transports[i]);
+ protocols[i] = p;
+ }
- await RunClientAsync(clientProtocol, cancellationToken);
+ Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}");
+
+ var tasks = new Task[numClients];
+ for (int i = 0; i < numClients; i++)
+ {
+ var task = RunClientAsync(protocols[i], cancellationToken);
+ tasks[i] = task;
+ }
+
+ Task.WaitAll(tasks);
+
+ await Task.CompletedTask;
}
private static TClientTransport GetTransport(string[] args)
@@ -112,20 +141,30 @@
case Transport.Http:
return new THttpClientTransport(new Uri("http://localhost:9090"), null);
case Transport.TcpBuffered:
- return
- new TBufferedClientTransport(
- new TSocketClientTransport(IPAddress.Loopback, 9090));
+ return new TBufferedClientTransport(new TSocketClientTransport(IPAddress.Loopback, 9090));
case Transport.TcpTls:
- return new TTlsSocketClientTransport(IPAddress.Loopback, 9090,
- GetCertificate(), CertValidator, LocalCertificateSelectionCallback);
+ return new TTlsSocketClientTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback);
case Transport.Framed:
- throw new NotSupportedException("Framed is not ready for samples");
+ return new TFramedClientTransport(new TSocketClientTransport(IPAddress.Loopback, 9090));
}
}
return new TSocketClientTransport(IPAddress.Loopback, 9090);
}
+ private static int GetNumberOfClients(string[] args)
+ {
+ var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':')?[1];
+
+ Logger.LogInformation($"Selected # of clients: {numClients}");
+
+ int c;
+ if( int.TryParse(numClients, out c) && (0 < c) && (c <= 100))
+ return c;
+ else
+ return 1;
+ }
+
private static X509Certificate2 GetCertificate()
{
// due to files location in net core better to take certs from top folder
@@ -162,7 +201,7 @@
return true;
}
- private static TProtocol GetProtocol(string[] args, TClientTransport transport)
+ private static Tuple<Protocol, TProtocol> GetProtocol(string[] args, TClientTransport transport)
{
var protocol = args.FirstOrDefault(x => x.StartsWith("-p"))?.Split(':')?[1];
@@ -172,79 +211,52 @@
switch (selectedProtocol)
{
case Protocol.Binary:
- return new TBinaryProtocol(transport);
+ return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport));
case Protocol.Compact:
- return new TCompactProtocol(transport);
+ return new Tuple<Protocol, TProtocol>(selectedProtocol, new TCompactProtocol(transport));
case Protocol.Json:
- return new TJsonProtocol(transport);
+ return new Tuple<Protocol, TProtocol>(selectedProtocol, new TJsonProtocol(transport));
+ case Protocol.Multiplexed:
+ // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol)
+ return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport));
}
}
- return new TBinaryProtocol(transport);
+ return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport));
}
- private static async Task RunClientAsync(TProtocol protocol,
- CancellationToken cancellationToken)
+ private static async Task RunClientAsync(Tuple<Protocol, TProtocol> protocolTuple, CancellationToken cancellationToken)
{
try
{
- var client = new Calculator.Client(protocol);
- await client.OpenTransportAsync(cancellationToken);
+ var protocol = protocolTuple.Item2;
+ var protocolType = protocolTuple.Item1;
+
+ TBaseClient client = null;
try
{
- // Async version
-
- Logger.LogInformation("PingAsync()");
- await client.pingAsync(cancellationToken);
-
- Logger.LogInformation("AddAsync(1,1)");
- var sum = await client.addAsync(1, 1, cancellationToken);
- Logger.LogInformation($"AddAsync(1,1)={sum}");
-
- var work = new Work
+ if (protocolType != Protocol.Multiplexed)
{
- Op = Operation.DIVIDE,
- Num1 = 1,
- Num2 = 0
- };
- try
- {
- Logger.LogInformation("CalculateAsync(1)");
- await client.calculateAsync(1, work, cancellationToken);
- Logger.LogInformation("Whoa we can divide by 0");
+ client = new Calculator.Client(protocol);
+ await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client);
}
- catch (InvalidOperation io)
+ else
{
- Logger.LogInformation("Invalid operation: " + io);
+ // it uses binary protocol there to create Multiplexed protocols
+ var multiplex = new TMultiplexedProtocol(protocol, nameof(Calculator));
+ client = new Calculator.Client(multiplex);
+ await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client);
+
+ multiplex = new TMultiplexedProtocol(protocol, nameof(SharedService));
+ client = new SharedService.Client(multiplex);
+ await ExecuteSharedServiceClientOperations(cancellationToken, (SharedService.Client)client);
}
-
- work.Op = Operation.SUBTRACT;
- work.Num1 = 15;
- work.Num2 = 10;
-
- try
- {
- Logger.LogInformation("CalculateAsync(1)");
- var diff = await client.calculateAsync(1, work, cancellationToken);
- Logger.LogInformation($"15-10={diff}");
- }
- catch (InvalidOperation io)
- {
- Logger.LogInformation("Invalid operation: " + io);
- }
-
- Logger.LogInformation("GetStructAsync(1)");
- var log = await client.getStructAsync(1, cancellationToken);
- Logger.LogInformation($"Check log: {log.Value}");
-
- Logger.LogInformation("ZipAsync() with delay 100mc on server side");
- await client.zipAsync(cancellationToken);
}
catch (Exception ex)
{
- Logger.LogError(ex.ToString());
+ Logger.LogError($"{client?.ClientId} " + ex);
}
finally
{
@@ -257,6 +269,71 @@
}
}
+ private static async Task ExecuteCalculatorClientOperations(CancellationToken cancellationToken, Calculator.Client client)
+ {
+ await client.OpenTransportAsync(cancellationToken);
+
+ // Async version
+
+ Logger.LogInformation($"{client.ClientId} PingAsync()");
+ await client.pingAsync(cancellationToken);
+
+ Logger.LogInformation($"{client.ClientId} AddAsync(1,1)");
+ var sum = await client.addAsync(1, 1, cancellationToken);
+ Logger.LogInformation($"{client.ClientId} AddAsync(1,1)={sum}");
+
+ var work = new Work
+ {
+ Op = Operation.DIVIDE,
+ Num1 = 1,
+ Num2 = 0
+ };
+
+ try
+ {
+ Logger.LogInformation($"{client.ClientId} CalculateAsync(1)");
+ await client.calculateAsync(1, work, cancellationToken);
+ Logger.LogInformation($"{client.ClientId} Whoa we can divide by 0");
+ }
+ catch (InvalidOperation io)
+ {
+ Logger.LogInformation($"{client.ClientId} Invalid operation: " + io);
+ }
+
+ work.Op = Operation.SUBTRACT;
+ work.Num1 = 15;
+ work.Num2 = 10;
+
+ try
+ {
+ Logger.LogInformation($"{client.ClientId} CalculateAsync(1)");
+ var diff = await client.calculateAsync(1, work, cancellationToken);
+ Logger.LogInformation($"{client.ClientId} 15-10={diff}");
+ }
+ catch (InvalidOperation io)
+ {
+ Logger.LogInformation($"{client.ClientId} Invalid operation: " + io);
+ }
+
+ Logger.LogInformation($"{client.ClientId} GetStructAsync(1)");
+ var log = await client.getStructAsync(1, cancellationToken);
+ Logger.LogInformation($"{client.ClientId} Check log: {log.Value}");
+
+ Logger.LogInformation($"{client.ClientId} ZipAsync() with delay 100mc on server side");
+ await client.zipAsync(cancellationToken);
+ }
+ private static async Task ExecuteSharedServiceClientOperations(CancellationToken cancellationToken, SharedService.Client client)
+ {
+ await client.OpenTransportAsync(cancellationToken);
+
+ // Async version
+
+ Logger.LogInformation($"{client.ClientId} SharedService GetStructAsync(1)");
+ var log = await client.getStructAsync(1, cancellationToken);
+ Logger.LogInformation($"{client.ClientId} SharedService Value: {log.Value}");
+ }
+
+
private enum Transport
{
Tcp,
@@ -272,6 +349,7 @@
Binary,
Compact,
Json,
+ Multiplexed
}
}
}
\ No newline at end of file
diff --git a/tutorial/netcore/Client/Properties/launchSettings.json b/tutorial/netcore/Client/Properties/launchSettings.json
index f351eeb..6b7b60d 100644
--- a/tutorial/netcore/Client/Properties/launchSettings.json
+++ b/tutorial/netcore/Client/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"Client": {
"commandName": "Project",
- "commandLineArgs": "-t:tcptls"
+ "commandLineArgs": "-p:multiplexed"
}
}
}
\ No newline at end of file
diff --git a/tutorial/netcore/README.md b/tutorial/netcore/README.md
index 18aac02..6b2f660 100644
--- a/tutorial/netcore/README.md
+++ b/tutorial/netcore/README.md
@@ -1,12 +1,35 @@
# Building of samples for different platforms
-Details:
-
-- [https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/index ](https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/index "https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/index ")
-- [https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog](https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog "https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog")
+# Reused components
+- NET Core Standard 1.6 (SDK 1.0.0-preview2-003121)
+- NET Core App 1.1
+
+# How to build
+- Download and install .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md)
+- Ensure that you have thrift.exe which supports netcore lib and it added to PATH
+- Go to current folder
+- Run **build.sh** or **build.cmd** from the root of cloned repository
+- Check tests in **src/Tests** folder
+- Continue with /tutorials/netcore
+
+# How to run
+
+Notes: dotnet run supports passing arguments to app after -- symbols (https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-run) - example: **dotnet run -- -h** will show help for app
+
+- build
+- go to folder (Client/Server)
+- run with specifying of correct parameters **dotnet run -t:tcp -p:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**)
+
+#Notes
+- Migration to .NET Standard 2.0 planned for later (Q1 2017) according to https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/
+- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.)
+
+#Known issues
+- In trace logging mode you can see some not important internal exceptions
+- Ubuntu 16.10 still not supported fully
+- There is some problems with .NET Core CLI and usage specific -r|--runtime for building and publishing projects with different target frameworks (netstandard1.6 and netcoreapp1.1)
# Running of samples
-
Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples
# NetCore Server
@@ -16,7 +39,7 @@
Server.exe -h
will diplay help information
- Server.exe -t:<transport> -p:<protocol>
+ Server.exe -t:<transport> -p:<protocol>
will run server with specified arguments (tcp transport and binary protocol by default)
Options:
@@ -27,12 +50,13 @@
namedpipe - namedpipe transport will be used (pipe address - "".test"")
http - http transport will be used (http address - ""localhost:9090"")
tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090)
+ framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
-p (protocol):
binary - (default) binary protocol will be used
compact - compact protocol will be used
json - json protocol will be used
-
+
Sample:
Server.exe -t:tcp
@@ -51,7 +75,7 @@
Client.exe -h
will diplay help information
- Client.exe -t:<transport> -p:<protocol>
+ Client.exe -t:<transport> -p:<protocol> -mc:<numClients>
will run client with specified arguments (tcp transport and binary protocol by default)
Options:
@@ -62,15 +86,19 @@
namedpipe - namedpipe transport will be used (pipe address - "".test"")
http - http transport will be used (address - ""http://localhost:9090"")
tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090)
+ framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
-p (protocol):
binary - (default) binary protocol will be used
compact - compact protocol will be used
json - json protocol will be used
+
+ -mc (multiple clients):
+ <numClients> - number of multiple clients to connect to server (max 100, default 1)
Sample:
- Client.exe -t:tcp -p:binary
+ Client.exe -t:tcp -p:binary -mc:10
Remarks:
@@ -250,4 +278,4 @@
# You could do one of these for a multithreaded server
# server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
# server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
-```
\ No newline at end of file
+```
diff --git a/tutorial/netcore/Server/Program.cs b/tutorial/netcore/Server/Program.cs
index 6041924..aa86ae3 100644
--- a/tutorial/netcore/Server/Program.cs
+++ b/tutorial/netcore/Server/Program.cs
@@ -40,7 +40,7 @@
{
public class Program
{
- private static readonly ILogger Logger = new LoggerFactory().CreateLogger(nameof(Server));
+ private static readonly ILogger Logger = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace).CreateLogger(nameof(Server));
public static void Main(string[] args)
{
@@ -61,11 +61,13 @@
Console.ReadLine();
source.Cancel();
}
+
+ Logger.LogInformation("Server stopped");
}
private static void DisplayHelp()
{
- Console.WriteLine(@"
+ Logger.LogInformation(@"
Usage:
Server.exe -h
will diplay help information
@@ -80,11 +82,13 @@
namedpipe - namedpipe transport will be used (pipe address - "".test"")
http - http transport will be used (http address - ""localhost:9090"")
tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090)
+ framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
-p (protocol):
binary - (default) binary protocol will be used
compact - compact protocol will be used
json - json protocol will be used
+ multiplexed - multiplexed protocol will be used
Sample:
Server.exe -t:tcp
@@ -102,9 +106,7 @@
}
else
{
- await
- RunSelectedConfigurationAsync(selectedTransport, selectedProtocol,
- cancellationToken);
+ await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken);
}
}
@@ -128,12 +130,11 @@
return selectedTransport;
}
- private static async Task RunSelectedConfigurationAsync(Transport transport,
- Protocol protocol, CancellationToken cancellationToken)
+ private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken)
{
- var fabric = new LoggerFactory();
+ var fabric = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace);
var handler = new CalculatorAsyncHandler();
- var processor = new Calculator.AsyncProcessor(handler);
+ ITAsyncProcessor processor = null;
TServerTransport serverTransport = null;
@@ -143,15 +144,16 @@
serverTransport = new TServerSocketTransport(9090);
break;
case Transport.TcpBuffered:
- serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000,
- useBufferedSockets: true);
+ serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, useBufferedSockets: true);
break;
case Transport.NamedPipe:
serverTransport = new TNamedPipeServerTransport(".test");
break;
case Transport.TcpTls:
- serverTransport = new TTlsServerSocketTransport(9090, false, GetCertificate(),
- ClientCertValidator, LocalCertificateSelectionCallback);
+ serverTransport = new TTlsServerSocketTransport(9090, false, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback);
+ break;
+ case Transport.Framed:
+ serverTransport = new TServerFramedTransport(9090);
break;
}
@@ -164,18 +166,39 @@
{
inputProtocolFactory = new TBinaryProtocol.Factory();
outputProtocolFactory = new TBinaryProtocol.Factory();
+ processor = new Calculator.AsyncProcessor(handler);
}
break;
case Protocol.Compact:
{
inputProtocolFactory = new TCompactProtocol.Factory();
outputProtocolFactory = new TCompactProtocol.Factory();
+ processor = new Calculator.AsyncProcessor(handler);
}
break;
case Protocol.Json:
{
inputProtocolFactory = new TJsonProtocol.Factory();
outputProtocolFactory = new TJsonProtocol.Factory();
+ processor = new Calculator.AsyncProcessor(handler);
+ }
+ break;
+ case Protocol.Multiplexed:
+ {
+ inputProtocolFactory = new TBinaryProtocol.Factory();
+ outputProtocolFactory = new TBinaryProtocol.Factory();
+
+ var calcHandler = new CalculatorAsyncHandler();
+ var calcProcessor = new Calculator.AsyncProcessor(calcHandler);
+
+ var sharedServiceHandler = new SharedServiceAsyncHandler();
+ var sharedServiceProcessor = new SharedService.AsyncProcessor(sharedServiceHandler);
+
+ var multiplexedProcessor = new TMultiplexedProcessor();
+ multiplexedProcessor.RegisterProcessor(nameof(Calculator), calcProcessor);
+ multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor);
+
+ processor = multiplexedProcessor;
}
break;
default:
@@ -185,10 +208,9 @@
try
{
Logger.LogInformation(
- $"Selected TAsyncServer with {serverTransport} transport and {inputProtocolFactory} protocol factories");
+ $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories");
- var server = new AsyncBaseServer(processor, serverTransport, inputProtocolFactory,
- outputProtocolFactory, fabric);
+ var server = new AsyncBaseServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric);
Logger.LogInformation("Starting the server...");
await server.ServeAsync(cancellationToken);
@@ -197,8 +219,6 @@
{
Logger.LogInformation(x.ToString());
}
-
- Logger.LogInformation("Server stopped.");
}
private static X509Certificate2 GetCertificate()
@@ -243,7 +263,8 @@
TcpBuffered,
NamedPipe,
Http,
- TcpTls
+ TcpTls,
+ Framed
}
private enum Protocol
@@ -251,6 +272,7 @@
Binary,
Compact,
Json,
+ Multiplexed
}
public class HttpServerSample
@@ -305,11 +327,10 @@
public class CalculatorAsyncHandler : Calculator.IAsync
{
- Dictionary<int, SharedStruct> _log;
+ private readonly Dictionary<int, SharedStruct> _log = new Dictionary<int, SharedStruct>();
public CalculatorAsyncHandler()
{
- _log = new Dictionary<int, SharedStruct>();
}
public async Task<SharedStruct> getStructAsync(int key,
@@ -347,7 +368,7 @@
break;
case Operation.MULTIPLY:
- val = w.Num1*w.Num2;
+ val = w.Num1 * w.Num2;
break;
case Operation.DIVIDE:
@@ -361,7 +382,7 @@
throw io;
}
- val = w.Num1/w.Num2;
+ val = w.Num1 / w.Num2;
break;
default:
@@ -393,5 +414,18 @@
await Task.Delay(100, CancellationToken.None);
}
}
+
+ public class SharedServiceAsyncHandler : SharedService.IAsync
+ {
+ public async Task<SharedStruct> getStructAsync(int key, CancellationToken cancellationToken)
+ {
+ Logger.LogInformation("GetStructAsync({0})", key);
+ return await Task.FromResult(new SharedStruct()
+ {
+ Key = key,
+ Value = "GetStructAsync"
+ });
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tutorial/netcore/Server/Properties/launchSettings.json b/tutorial/netcore/Server/Properties/launchSettings.json
index e23253d..78076ff 100644
--- a/tutorial/netcore/Server/Properties/launchSettings.json
+++ b/tutorial/netcore/Server/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"Server": {
"commandName": "Project",
- "commandLineArgs": "-t:tcptls"
+ "commandLineArgs": "-p:multiplexed"
}
}
}
\ No newline at end of file
diff --git a/tutorial/netcore/global.json b/tutorial/netcore/global.json
index 53f1811..5ecfc21 100644
--- a/tutorial/netcore/global.json
+++ b/tutorial/netcore/global.json
@@ -1,3 +1,6 @@
{
- "projects": [ "../../lib/netcore" ]
+ "projects": [ "../../lib/netcore" ],
+ "sdk": {
+ "version": "1.0.0-preview2-1-003177" // "1.0.0-preview2-003121", "1.0.0-preview4-004233"
+ }
}
\ No newline at end of file