static async Task EndToEndTest() { var httpAddress = $"http://localhost/test"; var tcpAddress = $"tcp://localhost:9999/tcpTest"; var host = new ServiceHostBuilder <Service>(InstanceMode.PerConnection) .WithCallback <ICallback>() //add websocket server .AddWebSocketServer(httpAddress, options => options.ReceiveBufferSize = 1024) //add tcp server .AddTcpServer(tcpAddress, options => { options.ReceiveBufferSize = 1024; }) .WithMessagePackSerializer() //it is the default .WithConsoleLogger() //default is empty .CreateHost(); host.ServiceInstanceCreated += service => { //configure service instances Console.WriteLine("Instance created"); }; await host.Open(); Console.WriteLine("Host is open"); var clientBuilder1 = new DuplexConnectionBuilder <IService, MyCallback>(InstanceMode.PerConnection) .WithWebSocketTransport(httpAddress, options => { //set connection options options.ReceiveBufferSize = 1024; }) .WithMessagePackSerializer() .WithConsoleLogger(); clientBuilder1.CallbackInstanceCreated += obj => { Console.WriteLine($"Created callback of type {obj.GetType()}"); var callback = (MyCallback)obj; //config the callback instance }; var client1 = await clientBuilder1.CreateConnection(); var client2 = await clientBuilder1.CreateConnection(); var msg = await client1.Echo("From Client 1"); Console.WriteLine(msg); msg = await client2.Echo("From Client 2"); Console.WriteLine(msg); msg = await client1.CallMeBack(); Console.WriteLine(msg); var client3 = await clientBuilder1.CreateConnection(); client3.FireAndForget("server is here now"); Console.WriteLine("client3 is here now"); //this should appear first var clientBuilder2 = new ConnectionBuilder <IOtherService>() .WithWebSocketTransport(httpAddress) .WithConsoleLogger(); var client4 = await clientBuilder2.CreateConnection(); msg = await client4.Echo("It is another Echo"); //another interface same Echo signature Console.WriteLine(msg); await Task.Delay(6000); Console.WriteLine("now with tcp"); var tcpCient = await new DuplexConnectionBuilder <IService, MyCallback>(InstanceMode.Single) .WithTcpTransport(tcpAddress) .WithConsoleLogger() .CreateConnection(); msg = await tcpCient.Echo("From TCP Client"); Console.WriteLine(msg); await tcpCient.CallMeBack(); //how to close connection, the listening will show exception that has no effect //await ((IConnection)client4).Close(); }
protected override async Task ExecuteAsync(CancellationToken cancellationToken) { var ip = _config.GetValue <String>("MonitorConnection:Address", "localhost"); var port = _config.GetValue <int>("MonitorConnection:Port", 5010); var address = $"tcp://{ip}:{port}/opengameserver"; //var builder = new DuplexConnectionBuilder<IMonitorComsInterface, MonitorComsCallback>(Xeeny.Dispatching.InstanceMode.Single) var builder = new DuplexConnectionBuilder <IMonitorComsInterface, MonitorComsCallback>(_serviceProvider.GetService <MonitorComsCallback>()) .WithTcpTransport(address, options => { options.Timeout = TimeSpan.FromSeconds(RetryTime); }); builder.CallbackInstanceCreated += (callback) => { //callback.eventHandlerService = _eventHandlerService; }; _logger.LogInformation("Trying to connect to the monitor."); while (!cancellationToken.IsCancellationRequested) { ComsClient = await builder.CreateConnection(false); var connection = ((IConnection)ComsClient); var task = connection.Connect(); await Task.WhenAny(task, Task.Delay((int)(RetryTime * 1000))); if (connection.State == Xeeny.Transports.ConnectionState.Connected) { _logger.LogInformation("Sending initial welcome to the Monitor!"); //var connectedTask = ComsClient.Connected(); await ComsClient.Connected(); _logger.LogInformation("Connected succesfully to the Monitor."); //await Task.WhenAny(connectedTask, TaskFromCancellationToken(cancellationToken)); while (!cancellationToken.IsCancellationRequested && connection.State == Xeeny.Transports.ConnectionState.Connected) { await Task.Delay((int)(RetryTime * 1000), cancellationToken); } if (connection.State == Xeeny.Transports.ConnectionState.Connected) { connection.Close(); } else if (!cancellationToken.IsCancellationRequested) { _logger.LogWarning("The connection to the Monitor has been lost! Retrying connection in {0} seconds.", RetryTime); await Task.Delay((int)(RetryTime * 1000), cancellationToken); } } else { if (connection.State == Xeeny.Transports.ConnectionState.Connecting) { connection.Close(); } _logger.LogWarning("Couldn't stablish connection to the Monitor... Retrying again in {0} seconds.", RetryTime); await Task.Delay((int)(RetryTime * 1000), cancellationToken); } } }
static async Task Main(string[] args) { try { var address = $"tcp://localhost:9091/test"; //note InstanceMode.Single var host = new ServiceHostBuilder <ChatService>(InstanceMode.Single) .WithCallback <ICallback>() .AddTcpServer(address, options => { options.ReceiveTimeout = TimeSpan.FromSeconds(10); }) .WithConsoleLogger() .CreateHost(); await host.Open(); Console.WriteLine("host is open"); var name1 = "Client 1"; var name2 = "Client 2"; var name3 = "Client 3"; var callback1 = new Callback { Name = name1 }; var callback2 = new Callback { Name = name2 }; var callback3 = new Callback { Name = name3 }; var client1 = await new DuplexConnectionBuilder <IChatService, Callback>(callback1) .WithTcpTransport(address, options => { //usually should be around half server ReceiveTimeout options.KeepAliveInterval = TimeSpan.FromSeconds(5); }) .WithConsoleLogger() .CreateConnection(); var client2 = await new DuplexConnectionBuilder <IChatService, Callback>(callback2) .WithTcpTransport(address, options => { //usually should be around half server ReceiveTimeout options.KeepAliveInterval = TimeSpan.FromSeconds(5); }) .WithConsoleLogger() .CreateConnection(); var builder3 = new DuplexConnectionBuilder <IChatService, Callback>(callback3) .WithTcpTransport(address, options => { //this is too slow comparing to server ReceiveTimeout //this client will timeout if it didn't send it's own application messages //within server ReceiveTimeout options.KeepAliveInterval = TimeSpan.FromSeconds(15); }) .WithConsoleLogger(); //let's open this explicitly, pass false so connection won't open var client3 = await builder3.CreateConnection(false); //now explicitly open a client that is created but not connected await((IConnection)client3).Connect(); client1.Join(name1); client2.Join(name2); client3.Join(name3); await client1.Say("Hello"); await client2.Say("All clients will see this message"); await client2.TellOthers($"{name2} doesn't get this message"); await client3.PrivateTo(name1, $"This is from {name3} to {name1} Only"); await Task.Delay(1000); Console.WriteLine("client3 will close"); //client3 leaves ((IConnection)client3).Close(); await Task.Delay(1000); await client1.WhoIsOnline(); //client3 connect again, keep-alive is slower than server ReceiverTimeout //so it will timeout from server side client3 = await builder3.CreateConnection(); client3.Join(name3); await client3.WhoIsOnline(); await Task.Delay(1000); Console.WriteLine("Waiting client3 to timeout"); await Task.Delay(15000); //More than Server ReceiveTimeout Console.WriteLine("Waiting client3 to timeout is done"); await client1.WhoIsOnline(); await Task.Delay(1000); Console.WriteLine("Test is done"); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Console.ReadLine(); } }