Exemple #1
0
        static async Task Main(string[] args)
        {
            // First argument: client number (otherwise 0)
            int clientNumber = 0;

            if (args.Length > 0 && int.TryParse(args[0], out int it))
            {
                clientNumber = it;
            }
            clientID += "-" + clientNumber;

            // Welcome message
            Log.Write("Welcome to the test client: " + clientID);

            // RPC initialization
            var demoRpcConfig = new RpcClientConfig {
                ClientID  = clientID,
                ServerUrl = "http://localhost:5000/rpc"
            };

            RpcMain.InitRpcClient(demoRpcConfig, AuthenticateClient, () => new List <RpcFunctions> {
                new BankClientRpc()
            }, defaultTimeoutMs: 1000, new DemoRpcCommandBacklog());

            // Run until killed
            while (true)
            {
                await Task.Delay(1000);
            }
        }
Exemple #2
0
        static async Task Main(string[] args)
        {
            // Welcome message
            Log.Write("Welcome to the simple demo client!");

            // RPC initialization, using two server function classes
            var serverDemo    = new DemoServerRpcStub();
            var serverCalc    = new CalcRpcStub();
            var demoRpcConfig = new RpcClientConfig {
                ClientID  = clientID,
                ServerUrl = "http://localhost:5000/rpc"
            };

            RpcMain.InitRpcClient(demoRpcConfig, AuthenticateClient, () => new List <RpcFunctions> {
                new DemoClientRpc(),
                new CalcRpc()
            });

            // Each few seconds, send commands to the server. Log the result.
            var random = new Random();

            while (true)
            {
                try {
                    // Send greeting
                    Log.Write("Sending greeting...");
                    var greeting = new Greeting {
                        Name     = "Andi",
                        MoreData = new SampleData {
                            Text = $"Hi server, now it is {DateTime.Now}"
                        }
                    };
                    await serverDemo.SayHelloToServer(greeting);

                    // Send calculation task. May fail on the remote side, when there is division by zero.
                    Log.Write("Successfully greeted. Now sending a little calculation task:");
                    int  a         = random.Next(1, 100);
                    int  b         = random.Next(0, 10);
                    long startTime = CoreUtils.TimeNow();
                    try {
                        int result = await serverCalc.DivideNumbers(a, b);

                        long runTime = CoreUtils.TimeNow() - startTime;
                        Log.Write($"{a}/{b}={result} (runtime: {runTime}ms)");
                    }
                    catch (RpcException ex) {
                        long runTime = CoreUtils.TimeNow() - startTime;
                        Log.Write($"{a}+{b}=Fail! (runtime: {runTime}ms; {ex.Type}: {ex.Message})");
                    }
                }
                catch (RpcException ex) {
                    Log.Write("Error: " + ex.Failure.Type + ": " + ex.Message);
                }

                // Wait a second before the next round
                await Task.Delay(1000);
            }
        }
Exemple #3
0
        static async Task Main(string[] args)
        {
            // First argument: client number
            int clientNumber = 0;

            if (args.Length > 0 && int.TryParse(args[0], out int it))
            {
                clientNumber = it;
            }
            else
            {
                throw new Exception("Must be started with client number as parameter");
            }
            clientID += "-" + clientNumber;

            // Welcome message
            Log.Write("Welcome to the test client: " + clientID);

            // RPC initialization
            var serverCalc    = new CalcRpcStub();
            var demoRpcConfig = new RpcClientConfig {
                ClientID  = clientID,
                ServerUrl = "http://localhost:5000/rpc"
            };

            RpcMain.InitRpcClient(demoRpcConfig, AuthenticateClient, () => new List <RpcFunctions> {
                new CalcRpc()
            });

            // Each 0-100 ms, send a simple calculation task to the server: a + b = ?
            // a is an ascending number, starting from clientNumber * 1000
            // b is a random number between 1 and 100.
            // Write the calculations in the file "{clientID}.calclog" (used in the RpcLibTest project)
            string filename = $"{clientID}.calclog";

            File.Delete(filename);
            int a      = clientNumber * 1000;
            var random = new Random();

            while (true)
            {
                long startTime = CoreUtils.TimeNow();;
                a++;
                int b = random.Next(1, 100);
                try {
                    int result = await serverCalc.AddNumbers(a, b);

                    long runTime = CoreUtils.TimeNow() - startTime;
                    Log.WriteToFile(filename, $"{a}+{b}={result} | {runTime}ms");
                }
                catch (RpcException ex) {
                    long runTime = CoreUtils.TimeNow() - startTime;
                    Log.WriteToFile(filename, $"{a}+{b}=? | {runTime}ms | Fail: {ex.Type}: {ex.Message}");
                }
                await Task.Delay(random.Next(0, 100));
            }
        }
Exemple #4
0
 /// <summary>
 /// Call this method at the beginning to enable the communication to the server, so that this client
 /// can both receive commands from the server and send commands to the server.
 /// </summary>
 /// <param name="clientMethods">A function which returns new instances of the client's RPC method implementations</param>
 /// <param name="clientConfig">The settings of this client</param>
 /// <param name="authAction">An action which authenticates the used HTTP client, e.g. by adding HTTP Basic Auth
 /// information according to the client.</param>
 /// <param name="commandBacklog">The backlog for storing failed commands to retry them later. May be null,
 ///     when only <see cref="RpcRetryStrategy.None"/> will be used.</param>
 public void Start(Func <IEnumerable <RpcFunctions> > clientMethods, RpcClientConfig clientConfig,
                   Action <HttpClient> authAction, IRpcCommandBacklog?commandBacklog)
 {
     if (isRunning)
     {
         return;
     }
     isRunning = true;
     // Remember client factory and settings
     this.clientMethods = clientMethods;
     this.clientConfig  = clientConfig;
     serverCache        = new RpcPeerCache(clientID: "", commandBacklog);
     // Create and authorize HTTP clients
     httpPull         = new HttpClient();
     httpPull.Timeout = TimeSpan.FromSeconds(RpcServerEngine.longPollingSeconds + 10); // Give some more seconds for timeout
     authAction(httpPull);
     httpPush         = new HttpClient();
     httpPush.Timeout = TimeSpan.FromMilliseconds(RpcCommand.defaultTimeoutMs);
     authAction(httpPush);
     // Loop to pull the next command for this client from the server, execute it (if not already executed before)
     // and send the response together with the next pull.
     _ = Task.Run(async() => {
         RpcCommandResult?lastResult = null;
         while (isRunning)
         {
             RpcCommand?next = null;
             try {
                 next = await PullFromServer(lastResult);
             }
             catch {
                 // Could not reach server. Try the same result report again.
                 await Task.Delay(1000); // Wait a second before trying again
             }
             if (next != null)
             {
                 lastResult = await ExecuteLocallyNow(next);
             }
         }
     });
     // Loop to execute (i.e. send to server) the next command in the queue.
     _ = Task.Run(async() => {
         while (isRunning)
         {
             RpcCommand?next = await serverCache.DequeueCommand(timeoutMs: -1);  // No timeout
             if (next != null)
             {
                 next.SetState(RpcCommandState.Sent);
                 await ExecuteOnServerNow(next);
                 // In case of a networking problem, wait a second before trying the next command
                 if (next.GetResult().Failure?.IsNetworkProblem ?? false)
                 {
                     await Task.Delay(1000);
                 }
             }
         }
     });
 }
Exemple #5
0
 /// <summary>
 /// Initialize the RPC client with the given configuration, authentication method
 /// server-side RPC functions, optionally default timeout in ms and optionally backlog for retrying failed commands.
 /// </summary>
 public static void InitRpcClient(RpcClientConfig config, Action <HttpClient> auth,
                                  Func <List <RpcFunctions> > rpcFunctions, int?defaultTimeoutMs = null, IRpcCommandBacklog?commandBacklog = null)
 {
     // Set default timeout
     if (defaultTimeoutMs != null)
     {
         RpcCommand.defaultTimeoutMs = defaultTimeoutMs.Value;
     }
     // Start client
     RpcClientEngine.Instance.Start(rpcFunctions, config, auth, commandBacklog);
 }
Exemple #6
0
        static async Task Main(string[] args)
        {
            // First argument: client number (otherwise 0)
            int clientNumber = 0;

            if (args.Length > 0 && int.TryParse(args[0], out int it))
            {
                clientNumber = it;
            }
            clientID += "-" + clientNumber;

            // Welcome message
            Log.Write("Welcome to the test client: " + clientID);

            // RPC initialization
            var bankServer    = new BankServerRpcStub();
            var demoRpcConfig = new RpcClientConfig {
                ClientID  = clientID,
                ServerUrl = "http://localhost:5000/rpc"
            };

            RpcMain.InitRpcClient(demoRpcConfig, AuthenticateClient, () => new List <RpcFunctions> {
            }, defaultTimeoutMs: 1000, new DemoRpcCommandBacklog());

            // See the RetryOnClientTest test project to understand what we are doing now.

            // Repeatedly, get the current account balance and send an increasing amount (1 ct, 2ct, 3ct, ...)
            // to the bank, which is still offline at the beginning. This is done for 20 seconds.
            // Each 5 seconds, change the owner name.
            string filename = $"{clientID}.banklog";

            // TODO bankServer.OnAddMoneyRetryFinished = (command) =>
            //    Log.WriteToFile(filename, $"{command.GetParam<int>(1)} | {command.GetResult().ResultJson} | retried");
            for (int i = 1; i <= 20; i++)
            {
                // Get current balance (no retry!)
                long startTime = CoreUtils.TimeNow();
                try {
                    int newCents = await bankServer.GetBalance(clientNumber);

                    long runTime = CoreUtils.TimeNow() - startTime;
                    Log.WriteToFile(filename, $"Now | {newCents} | {runTime}ms");
                }
                catch (RpcException ex) {
                    long runTime = CoreUtils.TimeNow() - startTime;
                    Log.WriteToFile(filename, $"Now | Fail: {ex.Type}: {ex.Message} | {runTime}ms");
                }

                // Add money (retry for each command)
                startTime = CoreUtils.TimeNow();;
                try {
                    int newCents = await bankServer.AddMoney(clientNumber, i);

                    long runTime = CoreUtils.TimeNow() - startTime;
                    Log.WriteToFile(filename, $"Add | {i} | {newCents} | {runTime}ms");
                }
                catch (RpcException ex) {
                    long runTime = CoreUtils.TimeNow() - startTime;
                    Log.WriteToFile(filename, $"Add | {i} | Fail: {ex.Type}: {ex.Message} | {runTime}ms");
                }

                // Change owner name (retry for newest call of command)
                if (i % 5 == 0)
                {
                    startTime = CoreUtils.TimeNow();
                    string newName = "MyName-" + (i / 5);
                    try {
                        await bankServer.ChangeOwnerName(clientNumber, newName);

                        long runTime = CoreUtils.TimeNow() - startTime;
                        Log.WriteToFile(filename, $"Name | {newName} | {runTime}ms");
                    }
                    catch (RpcException ex) {
                        long runTime = CoreUtils.TimeNow() - startTime;
                        Log.WriteToFile(filename, $"Name | {newName} | Fail: {ex.Type}: {ex.Message} | {runTime}ms");
                    }
                }

                await Task.Delay(1000);
            }

            // Finished. Close client.
        }