From 0d12832d92351f2cbb2c59edaeb114f789c0ec9b Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 25 Feb 2021 09:42:52 +0100 Subject: misc. netstd improvements Client: netstd Patch: Jens Geyer This closes #2344 --- tutorial/netstd/Client/Program.cs | 221 ++++++++++----------- .../netstd/Client/Properties/launchSettings.json | 8 - tutorial/netstd/Server/Program.cs | 154 +++++++------- .../netstd/Server/Properties/launchSettings.json | 8 - 4 files changed, 193 insertions(+), 198 deletions(-) delete mode 100644 tutorial/netstd/Client/Properties/launchSettings.json delete mode 100644 tutorial/netstd/Server/Properties/launchSettings.json (limited to 'tutorial') diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs index abbba702e..f3e93ceb0 100644 --- a/tutorial/netstd/Client/Program.cs +++ b/tutorial/netstd/Client/Program.cs @@ -34,11 +34,14 @@ using Thrift.Transport.Client; using tutorial; using shared; +#pragma warning disable IDE0063 // using +#pragma warning disable IDE0057 // substr + namespace Client { public class Program { - private static ServiceCollection ServiceCollection = new ServiceCollection(); + private static readonly ServiceCollection ServiceCollection = new ServiceCollection(); private static ILogger Logger; private static readonly TConfiguration Configuration = null; // new TConfiguration() if needed @@ -49,26 +52,27 @@ Usage: Client -help will diplay help information - Client -tr: -bf: -pr: -mc: + Client -tr: -bf: -pr: [-mc:] [-multiplex] will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client Options: -tr (transport): - tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - 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) + tcp - (default) tcp transport (localhost:9090) + tcptls - tcp tls transport (localhost:9090) + namedpipe - namedpipe transport (pipe "".test"") + http - http transport (http://localhost:9090) -bf (buffering): - none - (default) no buffering will be used - buffered - buffered transport will be used - framed - framed transport will be used + none - (default) no buffering + buffered - buffered transport + framed - framed transport -pr (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 + binary - (default) binary protocol + compact - compact protocol + json - json protocol + + -multiplex - adds multiplexed protocol -mc (multiple clients): - number of multiple clients to connect to server (max 100, default 1) @@ -80,7 +84,7 @@ Sample: public static void Main(string[] args) { - args = args ?? new string[0]; + args ??= Array.Empty(); ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); using (var serviceProvider = ServiceCollection.BuildServiceProvider()) @@ -115,43 +119,77 @@ Sample: Logger.LogInformation($"Selected # of clients: {numClients}"); - var transports = new TTransport[numClients]; - for (int i = 0; i < numClients; i++) - { - var t = GetTransport(args); - transports[i] = t; - } - - Logger.LogInformation($"Selected client transport: {transports[0]}"); + var transport = GetTransport(args); + Logger.LogInformation($"Selected client transport: {transport}"); - var protocols = new Tuple[numClients]; - for (int i = 0; i < numClients; i++) - { - var p = GetProtocol(args, transports[i]); - protocols[i] = p; - } + var protocol = MakeProtocol( args, MakeTransport(args)); + Logger.LogInformation($"Selected client protocol: {GetProtocol(args)}"); - Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}"); + var mplex = GetMultiplex(args); + Logger.LogInformation("Multiplex " + (mplex ? "yes" : "no")); var tasks = new Task[numClients]; for (int i = 0; i < numClients; i++) { - var task = RunClientAsync(protocols[i], cancellationToken); + var task = RunClientAsync(protocol, mplex, cancellationToken); tasks[i] = task; } - Task.WaitAll(tasks); - + Task.WaitAll(tasks,cancellationToken); await Task.CompletedTask; } - private static TTransport GetTransport(string[] args) + private static bool GetMultiplex(string[] args) { - TTransport transport = new TSocketTransport(IPAddress.Loopback, 9090, Configuration); + var mplex = args.FirstOrDefault(x => x.StartsWith("-multiplex")); + return !string.IsNullOrEmpty(mplex); + } + private static Protocol GetProtocol(string[] args) + { + var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + if (string.IsNullOrEmpty(protocol)) + return Protocol.Binary; + + protocol = protocol.Substring(0, 1).ToUpperInvariant() + protocol.Substring(1).ToLowerInvariant(); + if (Enum.TryParse(protocol, true, out Protocol selectedProtocol)) + return selectedProtocol; + else + return Protocol.Binary; + } + + private static Buffering GetBuffering(string[] args) + { + var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1]; + if (string.IsNullOrEmpty(buffering)) + return Buffering.None; + + buffering = buffering.Substring(0, 1).ToUpperInvariant() + buffering.Substring(1).ToLowerInvariant(); + if (Enum.TryParse(buffering, out var selectedBuffering)) + return selectedBuffering; + else + return Buffering.None; + } + + private static Transport GetTransport(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + if (string.IsNullOrEmpty(transport)) + return Transport.Tcp; + + transport = transport.Substring(0, 1).ToUpperInvariant() + transport.Substring(1).ToLowerInvariant(); + if (Enum.TryParse(transport, true, out Transport selectedTransport)) + return selectedTransport; + else + return Transport.Tcp; + } + + + private static TTransport MakeTransport(string[] args) + { // construct endpoint transport - var transportArg = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; - if (Enum.TryParse(transportArg, true, out Transport selectedTransport)) + TTransport transport = null; + Transport selectedTransport = GetTransport(args); { switch (selectedTransport) { @@ -179,23 +217,20 @@ Sample: } // optionally add layered transport(s) - var bufferingArg = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(':')?[1]; - if (Enum.TryParse(bufferingArg, out var selectedBuffering)) + Buffering selectedBuffering = GetBuffering(args); + switch (selectedBuffering) { - switch (selectedBuffering) - { - case Buffering.Buffered: - transport = new TBufferedTransport(transport); - break; + case Buffering.Buffered: + transport = new TBufferedTransport(transport); + break; - case Buffering.Framed: - transport = new TFramedTransport(transport); - break; + case Buffering.Framed: + transport = new TFramedTransport(transport); + break; - default: // layered transport(s) are optional - Debug.Assert(selectedBuffering == Buffering.None, "unhandled case"); - break; - } + default: // layered transport(s) are optional + Debug.Assert(selectedBuffering == Buffering.None, "unhandled case"); + break; } return transport; @@ -207,11 +242,10 @@ Sample: Logger.LogInformation($"Selected # of clients: {numClients}"); - int c; - if( int.TryParse(numClients, out c) && (0 < c) && (c <= 100)) - return c; - else - return 1; + if (int.TryParse(numClients, out int c) && (0 < c) && (c <= 100)) + return c; + else + return 1; } private static X509Certificate2 GetCertificate() @@ -250,65 +284,37 @@ Sample: return true; } - private static Tuple GetProtocol(string[] args, TTransport transport) + private static TProtocol MakeProtocol(string[] args, TTransport transport) { - var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; - - Protocol selectedProtocol; - if (Enum.TryParse(protocol, true, out selectedProtocol)) + Protocol selectedProtocol = GetProtocol(args); + switch (selectedProtocol) { - switch (selectedProtocol) - { - case Protocol.Binary: - return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); - case Protocol.Compact: - return new Tuple(selectedProtocol, new TCompactProtocol(transport)); - case Protocol.Json: - return new Tuple(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(selectedProtocol, new TBinaryProtocol(transport)); - default: - Debug.Assert(false, "unhandled case"); - break; - } + case Protocol.Binary: + return new TBinaryProtocol(transport); + case Protocol.Compact: + return new TCompactProtocol(transport); + case Protocol.Json: + return new TJsonProtocol(transport); + default: + throw new Exception("unhandled protocol"); } - - return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); } - private static async Task RunClientAsync(Tuple protocolTuple, CancellationToken cancellationToken) + private static async Task RunClientAsync(TProtocol protocol, bool multiplex, CancellationToken cancellationToken) { try { - var protocol = protocolTuple.Item2; - var protocolType = protocolTuple.Item1; - - TBaseClient client = null; - try { - if (protocolType != Protocol.Multiplexed) - { - - client = new Calculator.Client(protocol); - await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); - } - else - { - // 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); - } + if( multiplex) + protocol = new TMultiplexedProtocol(protocol, nameof(Calculator)); + + var client = new Calculator.Client(protocol); + await ExecuteCalculatorClientOperations(client, cancellationToken); } catch (Exception ex) { - Logger.LogError($"{client?.ClientId} " + ex); + Logger.LogError(ex.ToString()); } finally { @@ -321,7 +327,7 @@ Sample: } } - private static async Task ExecuteCalculatorClientOperations(CancellationToken cancellationToken, Calculator.Client client) + private static async Task ExecuteCalculatorClientOperations( Calculator.Client client, CancellationToken cancellationToken) { await client.OpenTransportAsync(cancellationToken); @@ -374,16 +380,6 @@ Sample: 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 @@ -401,7 +397,6 @@ Sample: Binary, Compact, Json, - Multiplexed } private enum Buffering diff --git a/tutorial/netstd/Client/Properties/launchSettings.json b/tutorial/netstd/Client/Properties/launchSettings.json deleted file mode 100644 index 6b7b60d78..000000000 --- a/tutorial/netstd/Client/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "Client": { - "commandName": "Project", - "commandLineArgs": "-p:multiplexed" - } - } -} \ No newline at end of file diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index 3181e8e33..df8f390aa 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -38,17 +38,20 @@ using shared; using Thrift.Processor; using System.Diagnostics; +#pragma warning disable IDE0063 // using +#pragma warning disable IDE0057 // substr + namespace Server { public class Program { - private static ServiceCollection ServiceCollection = new ServiceCollection(); + private static readonly ServiceCollection ServiceCollection = new ServiceCollection(); private static ILogger Logger; private static readonly TConfiguration Configuration = null; // new TConfiguration() if needed public static void Main(string[] args) { - args = args ?? new string[0]; + args ??= Array.Empty(); ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); using (var serviceProvider = ServiceCollection.BuildServiceProvider()) @@ -89,26 +92,27 @@ Usage: Server -help will diplay help information - Server -tr: -bf: -pr: + Server -tr: -bf: -pr: [-multiplex] will run server with specified arguments (tcp transport, no buffering, and binary protocol by default) Options: -tr (transport): - tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - 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) + tcp - (default) tcp transport (localhost:9090) + tcptls - tcp transport with tls (localhost:9090) + namedpipe - namedpipe transport (pipe "".test"") + http - http transport (localhost:9090) -bf (buffering): - none - (default) no buffering will be used - buffered - buffered transport will be used - framed - framed transport will be used + none - (default) no buffering + buffered - buffered transport + framed - framed transport -pr (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 + binary - (default) binary protocol + compact - compact protocol + json - json protocol + + -multiplex - adds multiplexed protocol Sample: Server -tr:tcp @@ -120,48 +124,68 @@ Sample: var selectedTransport = GetTransport(args); var selectedBuffering = GetBuffering(args); var selectedProtocol = GetProtocol(args); + var multiplex = GetMultiplex(args); if (selectedTransport == Transport.Http) { + if (multiplex) + throw new Exception("This tutorial semple code does not yet allow multiplex over http (although Thrift itself of course does)"); new HttpServerSample().Run(cancellationToken); } else { - await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, cancellationToken); + await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, multiplex, cancellationToken); } } - private static Protocol GetProtocol(string[] args) + + private static bool GetMultiplex(string[] args) { - var transport = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + var mplex = args.FirstOrDefault(x => x.StartsWith("-multiplex")); + return !string.IsNullOrEmpty(mplex); + } - Enum.TryParse(transport, true, out Protocol selectedProtocol); + private static Protocol GetProtocol(string[] args) + { + var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + if (string.IsNullOrEmpty(protocol)) + return Protocol.Binary; - return selectedProtocol; + protocol = protocol.Substring(0, 1).ToUpperInvariant() + protocol.Substring(1).ToLowerInvariant(); + if (Enum.TryParse(protocol, true, out Protocol selectedProtocol)) + return selectedProtocol; + else + return Protocol.Binary; } private static Buffering GetBuffering(string[] args) { var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1]; + if (string.IsNullOrEmpty(buffering)) + return Buffering.None; - Enum.TryParse(buffering, out var selectedBuffering); - - return selectedBuffering; + buffering = buffering.Substring(0, 1).ToUpperInvariant() + buffering.Substring(1).ToLowerInvariant(); + if( Enum.TryParse(buffering, out var selectedBuffering)) + return selectedBuffering; + else + return Buffering.None; } private static Transport GetTransport(string[] args) { var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + if (string.IsNullOrEmpty(transport)) + return Transport.Tcp; - Enum.TryParse(transport, true, out Transport selectedTransport); - - return selectedTransport; + transport = transport.Substring(0, 1).ToUpperInvariant() + transport.Substring(1).ToLowerInvariant(); + if( Enum.TryParse(transport, true, out Transport selectedTransport)) + return selectedTransport; + else + return Transport.Tcp; } - private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, CancellationToken cancellationToken) + private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, bool multiplex, CancellationToken cancellationToken) { - var handler = new CalculatorAsyncHandler(); - TServerTransport serverTransport = null; switch (transport) { @@ -177,18 +201,15 @@ Sample: break; } - TTransportFactory inputTransportFactory = null; - TTransportFactory outputTransportFactory = null; + TTransportFactory transportFactory = null; switch (buffering) { case Buffering.Buffered: - inputTransportFactory = new TBufferedTransport.Factory(); - outputTransportFactory = new TBufferedTransport.Factory(); + transportFactory = new TBufferedTransport.Factory(); break; case Buffering.Framed: - inputTransportFactory = new TFramedTransport.Factory(); - outputTransportFactory = new TFramedTransport.Factory(); + transportFactory = new TFramedTransport.Factory(); break; default: // layered transport(s) are optional @@ -196,65 +217,57 @@ Sample: break; } - TProtocolFactory inputProtocolFactory = null; - TProtocolFactory outputProtocolFactory = null; - ITAsyncProcessor processor = null; + TProtocolFactory protocolFactory = null; switch (protocol) { case Protocol.Binary: - inputProtocolFactory = new TBinaryProtocol.Factory(); - outputProtocolFactory = new TBinaryProtocol.Factory(); - processor = new Calculator.AsyncProcessor(handler); + protocolFactory = new TBinaryProtocol.Factory(); break; case Protocol.Compact: - inputProtocolFactory = new TCompactProtocol.Factory(); - outputProtocolFactory = new TCompactProtocol.Factory(); - processor = new Calculator.AsyncProcessor(handler); + protocolFactory = new TCompactProtocol.Factory(); break; case Protocol.Json: - inputProtocolFactory = new TJsonProtocol.Factory(); - outputProtocolFactory = new TJsonProtocol.Factory(); - processor = new Calculator.AsyncProcessor(handler); + protocolFactory = new TJsonProtocol.Factory(); 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); + default: + throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); + } - var multiplexedProcessor = new TMultiplexedProcessor(); - multiplexedProcessor.RegisterProcessor(nameof(Calculator), calcProcessor); - multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor); + var handler = new CalculatorAsyncHandler(); + ITAsyncProcessor processor = new Calculator.AsyncProcessor(handler); - processor = multiplexedProcessor; - break; + if (multiplex) + { + var multiplexedProcessor = new TMultiplexedProcessor(); + multiplexedProcessor.RegisterProcessor(nameof(Calculator), processor); - default: - throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); + processor = multiplexedProcessor; } try { Logger.LogInformation( - $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); + string.Format( + "TSimpleAsyncServer with \n{0} transport\n{1} buffering\nmultiplex = {2}\n{3} protocol", + transport, + buffering, + multiplex ? "yes" : "no", + protocol + )); var loggerFactory = ServiceCollection.BuildServiceProvider().GetService(); var server = new TSimpleAsyncServer( itProcessorFactory: new TSingletonProcessorFactory(processor), serverTransport: serverTransport, - inputTransportFactory: inputTransportFactory, - outputTransportFactory: outputTransportFactory, - inputProtocolFactory: inputProtocolFactory, - outputProtocolFactory: outputProtocolFactory, + inputTransportFactory: transportFactory, + outputTransportFactory: transportFactory, + inputProtocolFactory: protocolFactory, + outputProtocolFactory: protocolFactory, logger: loggerFactory.CreateLogger()); Logger.LogInformation("Starting the server..."); @@ -323,7 +336,6 @@ Sample: Binary, Compact, Json, - Multiplexed } public class HttpServerSample @@ -364,6 +376,8 @@ Sample: // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + // NOTE: this is not really the recommended way to do it + // because the HTTP server cannot be configured properly to e.g. accept framed or multiplex services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -372,6 +386,8 @@ Sample: // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { + _ = env; + _ = loggerFactory; app.UseMiddleware(); } } @@ -408,7 +424,7 @@ Sample: { Logger.LogInformation($"CalculateAsync({logid}, [{w.Op},{w.Num1},{w.Num2}])"); - var val = 0; + int val; switch (w.Op) { case Operation.ADD: diff --git a/tutorial/netstd/Server/Properties/launchSettings.json b/tutorial/netstd/Server/Properties/launchSettings.json deleted file mode 100644 index 78076ff7c..000000000 --- a/tutorial/netstd/Server/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "Server": { - "commandName": "Project", - "commandLineArgs": "-p:multiplexed" - } - } -} \ No newline at end of file -- cgit v1.2.1