Repository: thrift Updated Branches: refs/heads/master 55f976e0d -> b62247e0e
THRIFT-4039 Update of Apache Thrift .Net Core lib Client: NetCore Patch: Volodymyr Gotra <vgo...@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 Project: http://git-wip-us.apache.org/repos/asf/thrift/repo Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/b62247e0 Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/b62247e0 Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/b62247e0 Branch: refs/heads/master Commit: b62247e0ea23139a9922a1de965357907319e937 Parents: 55f976e Author: Volodymyr Gotra <vgo...@gmail.com> Authored: Mon Jan 16 02:34:28 2017 +0200 Committer: Jens Geyer <je...@apache.org> Committed: Wed Jan 25 00:04:45 2017 +0100 ---------------------------------------------------------------------- lib/netcore/README.md | 30 ++- lib/netcore/Thrift/TBaseClient.cs | 1 + .../Transports/Client/TFramedClientTransport.cs | 2 - .../Transports/Server/TServerFramedTransport.cs | 150 +++++++++++++ lib/netcore/global.json | 5 +- test/netcore/README.md | 17 ++ test/netcore/global.json | 5 +- tutorial/netcore/Client/Program.cs | 214 +++++++++++++------ .../Client/Properties/launchSettings.json | 2 +- tutorial/netcore/README.md | 48 ++++- tutorial/netcore/Server/Program.cs | 80 +++++-- .../Server/Properties/launchSettings.json | 2 +- tutorial/netcore/global.json | 5 +- 13 files changed, 445 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/lib/netcore/README.md ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/lib/netcore/Thrift/TBaseClient.cs ---------------------------------------------------------------------- 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 @@ namespace Thrift private readonly TProtocol _outputProtocol; private bool _isDisposed; private int _seqId; + public readonly Guid ClientId = Guid.NewGuid(); protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol) { http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs ---------------------------------------------------------------------- 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 @@ namespace Thrift.Transports.Client public TFramedClientTransport(TClientTransport transport) { - throw new NotImplementedException("TFramedClientTransport is not fully ready for usage"); - if (transport == null) { throw new ArgumentNullException(nameof(transport)); http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/lib/netcore/global.json ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/test/netcore/README.md ---------------------------------------------------------------------- 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 + http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/test/netcore/global.json ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/tutorial/netcore/Client/Program.cs ---------------------------------------------------------------------- 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 @@ namespace Client { 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 @@ Options: 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 @@ Sample: return; } + Logger.LogInformation("Starting client..."); using (var source = new CancellationTokenSource()) { @@ -85,15 +91,38 @@ Sample: private static async Task RunAsync(string[] args, CancellationToken cancellationToken) { - var clientTransport = GetTransport(args); + var numClients = GetNumberOfClients(args); + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + 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]}"); + + var protocols = new Tuple<Protocol, TProtocol>[numClients]; + for (int i = 0; i < numClients; i++) + { + var p = GetProtocol(args, transports[i]); + protocols[i] = p; + } - Logger.LogInformation($"Selected client transport: {clientTransport}"); + Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}"); - var clientProtocol = GetProtocol(args, clientTransport); + var tasks = new Task[numClients]; + for (int i = 0; i < numClients; i++) + { + var task = RunClientAsync(protocols[i], cancellationToken); + tasks[i] = task; + } - Logger.LogInformation($"Selected client protocol: {clientProtocol}"); + Task.WaitAll(tasks); - await RunClientAsync(clientProtocol, cancellationToken); + await Task.CompletedTask; } private static TClientTransport GetTransport(string[] args) @@ -112,20 +141,30 @@ Sample: 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 @@ Sample: 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 @@ Sample: 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 - { - Op = Operation.DIVIDE, - Num1 = 1, - Num2 = 0 - }; - - try + if (protocolType != Protocol.Multiplexed) { - Logger.LogInformation("CalculateAsync(1)"); - await client.calculateAsync(1, work, cancellationToken); - Logger.LogInformation("Whoa we can divide by 0"); - } - catch (InvalidOperation io) - { - Logger.LogInformation("Invalid operation: " + io); - } - - 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}"); + 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); } - - 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 @@ Sample: } } + 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 @@ Sample: Binary, Compact, Json, + Multiplexed } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/tutorial/netcore/Client/Properties/launchSettings.json ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/tutorial/netcore/README.md ---------------------------------------------------------------------- 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 -# Running of samples +# 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 @@ Usage: 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 @@ Options: 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 @@ Usage: 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 @@ Options: 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 @@ if __name__ == '__main__': # 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 +``` http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/tutorial/netcore/Server/Program.cs ---------------------------------------------------------------------- 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 @@ namespace Server { 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 @@ namespace Server 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 @@ Options: 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 @@ Sample: } else { - await - RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, - cancellationToken); + await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken); } } @@ -128,12 +130,11 @@ Sample: 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 @@ Sample: 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 @@ Sample: { 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 @@ Sample: 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 @@ Sample: { Logger.LogInformation(x.ToString()); } - - Logger.LogInformation("Server stopped."); } private static X509Certificate2 GetCertificate() @@ -243,7 +263,8 @@ Sample: TcpBuffered, NamedPipe, Http, - TcpTls + TcpTls, + Framed } private enum Protocol @@ -251,6 +272,7 @@ Sample: Binary, Compact, Json, + Multiplexed } public class HttpServerSample @@ -305,11 +327,10 @@ Sample: 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 @@ Sample: break; case Operation.MULTIPLY: - val = w.Num1*w.Num2; + val = w.Num1 * w.Num2; break; case Operation.DIVIDE: @@ -361,7 +382,7 @@ Sample: throw io; } - val = w.Num1/w.Num2; + val = w.Num1 / w.Num2; break; default: @@ -393,5 +414,18 @@ Sample: 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/tutorial/netcore/Server/Properties/launchSettings.json ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/b62247e0/tutorial/netcore/global.json ---------------------------------------------------------------------- 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