-
Notifications
You must be signed in to change notification settings - Fork 1
Examples
Welcome, this wiki serves as a place to find examples for NetServer; These have been taken directly from the parent project NetCoreServer. They have been added here for your convenience.
Here comes the example of the TCP chat server. It handles multiple TCP client sessions and multicast received message from any session to all ones. Also it is possible to send admin message directly from the server.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using NetCoreServer;
namespace TcpChatServer
{
class ChatSession : TcpSession
{
public ChatSession(TcpServer server) : base(server) {}
protected override void OnConnected()
{
Console.WriteLine($"Chat TCP session with Id {Id} connected!");
// Send invite message
string message = "Hello from TCP chat! Please send a message or '!' to disconnect the client!";
SendAsync(message);
}
protected override void OnDisconnected()
{
Console.WriteLine($"Chat TCP session with Id {Id} disconnected!");
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
Console.WriteLine("Incoming: " + message);
// Multicast message to all connected sessions
Server.Multicast(message);
// If the buffer starts with '!' the disconnect the current session
if (message == "!")
Disconnect();
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Chat TCP session caught an error with code {error}");
}
}
class ChatServer : TcpServer
{
public ChatServer(IPAddress address, int port) : base(address, port) {}
protected override TcpSession CreateSession() { return new ChatSession(this); }
protected override void OnError(SocketError error)
{
Console.WriteLine($"Chat TCP server caught an error with code {error}");
}
}
class Program
{
static void Main(string[] args)
{
// TCP server port
int port = 1111;
if (args.Length > 0)
port = int.Parse(args[0]);
Console.WriteLine($"TCP server port: {port}");
Console.WriteLine();
// Create a new TCP chat server
var server = new ChatServer(IPAddress.Any, port);
// Start the server
Console.Write("Server starting...");
server.Start();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Restart the server
if (line == "!")
{
Console.Write("Server restarting...");
server.Restart();
Console.WriteLine("Done!");
continue;
}
// Multicast admin message to all sessions
line = "(admin) " + line;
server.Multicast(line);
}
// Stop the server
Console.Write("Server stopping...");
server.Stop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the TCP chat client. It connects to the TCP chat server and allows to send message to it and receive new messages.
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using TcpClient = NetCoreServer.TcpClient;
namespace TcpChatClient
{
class ChatClient : TcpClient
{
public ChatClient(string address, int port) : base(address, port) {}
public void DisconnectAndStop()
{
_stop = true;
DisconnectAsync();
while (IsConnected)
Thread.Yield();
}
protected override void OnConnected()
{
Console.WriteLine($"Chat TCP client connected a new session with Id {Id}");
}
protected override void OnDisconnected()
{
Console.WriteLine($"Chat TCP client disconnected a session with Id {Id}");
// Wait for a while...
Thread.Sleep(1000);
// Try to connect again
if (!_stop)
ConnectAsync();
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
Console.WriteLine(Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Chat TCP client caught an error with code {error}");
}
private bool _stop;
}
class Program
{
static void Main(string[] args)
{
// TCP server address
string address = "127.0.0.1";
if (args.Length > 0)
address = args[0];
// TCP server port
int port = 1111;
if (args.Length > 1)
port = int.Parse(args[1]);
Console.WriteLine($"TCP server address: {address}");
Console.WriteLine($"TCP server port: {port}");
Console.WriteLine();
// Create a new TCP chat client
var client = new ChatClient(address, port);
// Connect the client
Console.Write("Client connecting...");
client.ConnectAsync();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Disconnect the client
if (line == "!")
{
Console.Write("Client disconnecting...");
client.DisconnectAsync();
Console.WriteLine("Done!");
continue;
}
// Send the entered text to the chat server
client.SendAsync(line);
}
// Disconnect the client
Console.Write("Client disconnecting...");
client.DisconnectAndStop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the SSL chat server. It handles multiple SSL client sessions and multicast received message from any session to all ones. Also it is possible to send admin message directly from the server.
This example is very similar to the TCP one except the code that prepares SSL context and handshake handler.
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using NetCoreServer;
namespace SslChatServer
{
class ChatSession : SslSession
{
public ChatSession(SslServer server) : base(server) {}
protected override void OnConnected()
{
Console.WriteLine($"Chat SSL session with Id {Id} connected!");
}
protected override void OnHandshaked()
{
Console.WriteLine($"Chat SSL session with Id {Id} handshaked!");
// Send invite message
string message = "Hello from SSL chat! Please send a message or '!' to disconnect the client!";
Send(message);
}
protected override void OnDisconnected()
{
Console.WriteLine($"Chat SSL session with Id {Id} disconnected!");
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
Console.WriteLine("Incoming: " + message);
// Multicast message to all connected sessions
Server.Multicast(message);
// If the buffer starts with '!' the disconnect the current session
if (message == "!")
Disconnect();
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Chat SSL session caught an error with code {error}");
}
}
class ChatServer : SslServer
{
public ChatServer(SslContext context, IPAddress address, int port) : base(context, address, port) {}
protected override SslSession CreateSession() { return new ChatSession(this); }
protected override void OnError(SocketError error)
{
Console.WriteLine($"Chat SSL server caught an error with code {error}");
}
}
class Program
{
static void Main(string[] args)
{
// SSL server port
int port = 2222;
if (args.Length > 0)
port = int.Parse(args[0]);
Console.WriteLine($"SSL server port: {port}");
Console.WriteLine();
// Create and prepare a new SSL server context
var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("server.pfx", "qwerty"));
// Create a new SSL chat server
var server = new ChatServer(context, IPAddress.Any, port);
// Start the server
Console.Write("Server starting...");
server.Start();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Restart the server
if (line == "!")
{
Console.Write("Server restarting...");
server.Restart();
Console.WriteLine("Done!");
continue;
}
// Multicast admin message to all sessions
line = "(admin) " + line;
server.Multicast(line);
}
// Stop the server
Console.Write("Server stopping...");
server.Stop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the SSL chat client. It connects to the SSL chat server and allows to send message to it and receive new messages.
This example is very similar to the TCP one except the code that prepares SSL context and handshake handler.
using System;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using NetCoreServer;
namespace SslChatClient
{
class ChatClient : SslClient
{
public ChatClient(SslContext context, string address, int port) : base(context, address, port) {}
public void DisconnectAndStop()
{
_stop = true;
DisconnectAsync();
while (IsConnected)
Thread.Yield();
}
protected override void OnConnected()
{
Console.WriteLine($"Chat SSL client connected a new session with Id {Id}");
}
protected override void OnHandshaked()
{
Console.WriteLine($"Chat SSL client handshaked a new session with Id {Id}");
}
protected override void OnDisconnected()
{
Console.WriteLine($"Chat SSL client disconnected a session with Id {Id}");
// Wait for a while...
Thread.Sleep(1000);
// Try to connect again
if (!_stop)
ConnectAsync();
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
Console.WriteLine(Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Chat SSL client caught an error with code {error}");
}
private bool _stop;
}
class Program
{
static void Main(string[] args)
{
// SSL server address
string address = "127.0.0.1";
if (args.Length > 0)
address = args[0];
// SSL server port
int port = 2222;
if (args.Length > 1)
port = int.Parse(args[1]);
Console.WriteLine($"SSL server address: {address}");
Console.WriteLine($"SSL server port: {port}");
Console.WriteLine();
// Create and prepare a new SSL client context
var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("client.pfx", "qwerty"), (sender, certificate, chain, sslPolicyErrors) => true);
// Create a new SSL chat client
var client = new ChatClient(context, address, port);
// Connect the client
Console.Write("Client connecting...");
client.ConnectAsync();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Disconnect the client
if (line == "!")
{
Console.Write("Client disconnecting...");
client.DisconnectAsync();
Console.WriteLine("Done!");
continue;
}
// Send the entered text to the chat server
client.SendAsync(line);
}
// Disconnect the client
Console.Write("Client disconnecting...");
client.DisconnectAndStop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the UDP echo server. It receives a datagram mesage from any UDP client and resend it back without any changes.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using NetCoreServer;
namespace UdpEchoServer
{
class EchoServer : UdpServer
{
public EchoServer(IPAddress address, int port) : base(address, port) {}
protected override void OnStarted()
{
// Start receive datagrams
ReceiveAsync();
}
protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size)
{
Console.WriteLine("Incoming: " + Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
// Echo the message back to the sender
SendAsync(endpoint, buffer, 0, size);
}
protected override void OnSent(EndPoint endpoint, long sent)
{
// Continue receive datagrams
ReceiveAsync();
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Echo UDP server caught an error with code {error}");
}
}
class Program
{
static void Main(string[] args)
{
// UDP server port
int port = 3333;
if (args.Length > 0)
port = int.Parse(args[0]);
Console.WriteLine($"UDP server port: {port}");
Console.WriteLine();
// Create a new UDP echo server
var server = new EchoServer(IPAddress.Any, port);
// Start the server
Console.Write("Server starting...");
server.Start();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Restart the server
if (line == "!")
{
Console.Write("Server restarting...");
server.Restart();
Console.WriteLine("Done!");
}
}
// Stop the server
Console.Write("Server stopping...");
server.Stop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the UDP echo client. It sends user datagram message to UDP server and listen for response.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UdpClient = NetCoreServer.UdpClient;
namespace UdpEchoClient
{
class EchoClient : UdpClient
{
public EchoClient(string address, int port) : base(address, port) {}
public void DisconnectAndStop()
{
_stop = true;
Disconnect();
while (IsConnected)
Thread.Yield();
}
protected override void OnConnected()
{
Console.WriteLine($"Echo UDP client connected a new session with Id {Id}");
// Start receive datagrams
ReceiveAsync();
}
protected override void OnDisconnected()
{
Console.WriteLine($"Echo UDP client disconnected a session with Id {Id}");
// Wait for a while...
Thread.Sleep(1000);
// Try to connect again
if (!_stop)
Connect();
}
protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size)
{
Console.WriteLine("Incoming: " + Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
// Continue receive datagrams
ReceiveAsync();
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Echo UDP client caught an error with code {error}");
}
private bool _stop;
}
class Program
{
static void Main(string[] args)
{
// UDP server address
string address = "127.0.0.1";
if (args.Length > 0)
address = args[0];
// UDP server port
int port = 3333;
if (args.Length > 1)
port = int.Parse(args[1]);
Console.WriteLine($"UDP server address: {address}");
Console.WriteLine($"UDP server port: {port}");
Console.WriteLine();
// Create a new TCP chat client
var client = new EchoClient(address, port);
// Connect the client
Console.Write("Client connecting...");
client.Connect();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Disconnect the client
if (line == "!")
{
Console.Write("Client disconnecting...");
client.Disconnect();
Console.WriteLine("Done!");
continue;
}
// Send the entered text to the chat server
client.Send(line);
}
// Disconnect the client
Console.Write("Client disconnecting...");
client.DisconnectAndStop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the UDP multicast server. It use multicast IP address to multicast datagram messages to all client that joined corresponding UDP multicast group.
using System;
using System.Net;
using System.Net.Sockets;
using NetCoreServer;
namespace UdpMulticastServer
{
class MulticastServer : UdpServer
{
public MulticastServer(IPAddress address, int port) : base(address, port) {}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Multicast UDP server caught an error with code {error}");
}
}
class Program
{
static void Main(string[] args)
{
// UDP multicast address
string multicastAddress = "239.255.0.1";
if (args.Length > 0)
multicastAddress = args[0];
// UDP multicast port
int multicastPort = 3334;
if (args.Length > 1)
multicastPort = int.Parse(args[1]);
Console.WriteLine($"UDP multicast address: {multicastAddress}");
Console.WriteLine($"UDP multicast port: {multicastPort}");
Console.WriteLine();
// Create a new UDP multicast server
var server = new MulticastServer(IPAddress.Any, 0);
// Start the multicast server
Console.Write("Server starting...");
server.Start(multicastAddress, multicastPort);
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Restart the server
if (line == "!")
{
Console.Write("Server restarting...");
server.Restart();
Console.WriteLine("Done!");
continue;
}
// Multicast admin message to all sessions
line = "(admin) " + line;
server.Multicast(line);
}
// Stop the server
Console.Write("Server stopping...");
server.Stop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the UDP multicast client. It use multicast IP address and joins UDP multicast group in order to receive multicasted datagram messages from UDP server.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UdpClient = NetCoreServer.UdpClient;
namespace UdpMulticastClient
{
class MulticastClient : UdpClient
{
public string Multicast;
public MulticastClient(string address, int port) : base(address, port) {}
public void DisconnectAndStop()
{
_stop = true;
Disconnect();
while (IsConnected)
Thread.Yield();
}
protected override void OnConnected()
{
Console.WriteLine($"Multicast UDP client connected a new session with Id {Id}");
// Join UDP multicast group
JoinMulticastGroup(Multicast);
// Start receive datagrams
ReceiveAsync();
}
protected override void OnDisconnected()
{
Console.WriteLine($"Multicast UDP client disconnected a session with Id {Id}");
// Wait for a while...
Thread.Sleep(1000);
// Try to connect again
if (!_stop)
Connect();
}
protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size)
{
Console.WriteLine("Incoming: " + Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
// Continue receive datagrams
ReceiveAsync();
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Multicast UDP client caught an error with code {error}");
}
private bool _stop;
}
class Program
{
static void Main(string[] args)
{
// UDP listen address
string listenAddress = "0.0.0.0";
if (args.Length > 0)
listenAddress = args[0];
// UDP multicast address
string multicastAddress = "239.255.0.1";
if (args.Length > 1)
multicastAddress = args[1];
// UDP multicast port
int multicastPort = 3334;
if (args.Length > 2)
multicastPort = int.Parse(args[2]);
Console.WriteLine($"UDP listen address: {listenAddress}");
Console.WriteLine($"UDP multicast address: {multicastAddress}");
Console.WriteLine($"UDP multicast port: {multicastPort}");
Console.WriteLine();
// Create a new TCP chat client
var client = new MulticastClient(listenAddress, multicastPort);
client.SetupMulticast(true);
client.Multicast = multicastAddress;
// Connect the client
Console.Write("Client connecting...");
client.Connect();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Disconnect the client
if (line == "!")
{
Console.Write("Client disconnecting...");
client.Disconnect();
Console.WriteLine("Done!");
continue;
}
}
// Disconnect the client
Console.Write("Client disconnecting...");
client.DisconnectAndStop();
Console.WriteLine("Done!");
}
}
}
Simple protocol is defined in simple.fbe file:
/*
Simple Fast Binary Encoding protocol for CppServer
https://github.com/chronoxor/FastBinaryEncoding
Generate protocol command: fbec --csharp --proto --input=simple.fbe --output=.
*/
// Domain declaration
domain com.chronoxor
// Package declaration
package simple
// Protocol version
version 1.0
// Simple request message
[request]
[response(SimpleResponse)]
[reject(SimpleReject)]
message SimpleRequest
{
// Request Id
uuid [id] = uuid1;
// Request message
string Message;
}
// Simple response
message SimpleResponse
{
// Response Id
uuid [id] = uuid1;
// Calculated message length
uint32 Length;
// Calculated message hash
uint32 Hash;
}
// Simple reject
message SimpleReject
{
// Reject Id
uuid [id] = uuid1;
// Error message
string Error;
}
// Simple notification
message SimpleNotify
{
// Server notification
string Notification;
}
// Disconnect request message
[request]
message DisconnectRequest
{
// Request Id
uuid [id] = uuid1;
}
Here comes the example of the simple protocol server. It process client requests, answer with corresponding responses and send server notifications back to clients.
using System;
using System.Net;
using System.Net.Sockets;
using NetCoreServer;
using com.chronoxor.simple;
using com.chronoxor.simple.FBE;
namespace ProtoServer
{
public class SimpleProtoSessionSender : Sender, ISenderListener
{
public SimpleProtoSession Session { get; }
public SimpleProtoSessionSender(SimpleProtoSession session) { Session = session; }
public long OnSend(byte[] buffer, long offset, long size)
{
return Session.SendAsync(buffer, offset, size) ? size : 0;
}
}
public class SimpleProtoSessionReceiver : Receiver, IReceiverListener
{
public SimpleProtoSession Session { get; }
public SimpleProtoSessionReceiver(SimpleProtoSession session) { Session = session; }
public void OnReceive(DisconnectRequest request) { Session.OnReceive(request); }
public void OnReceive(SimpleRequest request) { Session.OnReceive(request); }
}
public class SimpleProtoSession : TcpSession
{
public SimpleProtoSessionSender Sender { get; }
public SimpleProtoSessionReceiver Receiver { get; }
public SimpleProtoSession(TcpServer server) : base(server)
{
Sender = new SimpleProtoSessionSender(this);
Receiver = new SimpleProtoSessionReceiver(this);
}
protected override void OnConnected()
{
Console.WriteLine($"TCP protocol session with Id '{Id}' connected to remote address '{(Socket.RemoteEndPoint as IPEndPoint)?.Address}' and port {(Socket.RemoteEndPoint as IPEndPoint)?.Port}");
// Send invite notification
SimpleNotify notify = SimpleNotify.Default;
notify.Notification = "Hello from Simple protocol server! Please send a message or '!' to disconnect the client!";
Sender.Send(notify);
}
protected override void OnDisconnected()
{
Console.WriteLine($"TCP protocol session with Id '{Id}' disconnected");
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
Receiver.Receive(buffer, offset, size);
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"TCP protocol session with Id '{Id}' caught a socket error: {error}");
}
// Protocol handlers
public void OnReceive(DisconnectRequest request) { Disconnect(); }
public void OnReceive(SimpleRequest request)
{
Console.WriteLine($"Received: {request}");
// Validate request
if (string.IsNullOrEmpty(request.Message))
{
// Send reject
SimpleReject reject = SimpleReject.Default;
reject.id = request.id;
reject.Error = "Request message is empty!";
Sender.Send(reject);
return;
}
// Send response
SimpleResponse response = SimpleResponse.Default;
response.id = request.id;
response.Hash = (uint)request.Message.GetHashCode();
response.Length = (uint)request.Message.Length;
Sender.Send(response);
}
}
public class SimpleProtoSender : Sender, ISenderListener
{
public SimpleProtoServer Server { get; }
public SimpleProtoSender(SimpleProtoServer server) { Server = server; }
public long OnSend(byte[] buffer, long offset, long size)
{
Server.Multicast(buffer, offset, size);
return size;
}
}
public class SimpleProtoServer : TcpServer
{
public SimpleProtoSender Sender { get; }
public SimpleProtoServer(IPAddress address, int port) : base(address, port)
{
Sender = new SimpleProtoSender(this);
}
protected override TcpSession CreateSession() { return new SimpleProtoSession(this); }
protected override void OnStarted()
{
Console.WriteLine($"Simple protocol server with Id '{Id}' started!");
}
protected override void OnStopped()
{
Console.WriteLine($"Simple protocol server with Id '{Id}' stopped!");
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"Simple protocol server with Id '{Id}' caught an error: {error}");
}
}
class Program
{
static void Main(string[] args)
{
// Simple protocol server port
int port = 4444;
if (args.Length > 0)
port = int.Parse(args[0]);
Console.WriteLine($"Simple protocol server port: {port}");
Console.WriteLine();
// Create a new simple protocol server
var server = new SimpleProtoServer(IPAddress.Any, port);
// Start the server
Console.Write("Server starting...");
server.Start();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Restart the server
if (line == "!")
{
Console.Write("Server restarting...");
server.Restart();
Console.WriteLine("Done!");
continue;
}
// Multicast admin notification to all sessions
SimpleNotify notify = SimpleNotify.Default;
notify.Notification = "(admin) " + line;
server.Sender.Send(notify);
}
// Stop the server
Console.Write("Server stopping...");
server.Stop();
Console.WriteLine("Done!");
}
}
}
Here comes the example of the simple protocol client. It connects to the simple protocol server and allows to send requests to it and receive corresponding responses.
using System;
using System.Net.Sockets;
using System.Threading;
using TcpClient = NetCoreServer.TcpClient;
using com.chronoxor.simple;
using com.chronoxor.simple.FBE;
namespace ProtoClient
{
public class TcpProtoClient : TcpClient
{
public TcpProtoClient(string address, int port) : base(address, port) {}
public bool ConnectAndStart()
{
Console.WriteLine($"TCP protocol client starting a new session with Id '{Id}'...");
StartReconnectTimer();
return ConnectAsync();
}
public bool DisconnectAndStop()
{
Console.WriteLine($"TCP protocol client stopping the session with Id '{Id}'...");
StopReconnectTimer();
DisconnectAsync();
return true;
}
public override bool Reconnect()
{
return ReconnectAsync();
}
private Timer _reconnectTimer;
public void StartReconnectTimer()
{
// Start the reconnect timer
_reconnectTimer = new Timer(state =>
{
Console.WriteLine($"TCP reconnect timer connecting the client session with Id '{Id}'...");
ConnectAsync();
}, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
}
public void StopReconnectTimer()
{
// Stop the reconnect timer
_reconnectTimer?.Dispose();
_reconnectTimer = null;
}
public delegate void ConnectedHandler();
public event ConnectedHandler Connected = () => {};
protected override void OnConnected()
{
Console.WriteLine($"TCP protocol client connected a new session with Id '{Id}' to remote address '{Address}' and port {Port}");
Connected?.Invoke();
}
public delegate void DisconnectedHandler();
public event DisconnectedHandler Disconnected = () => {};
protected override void OnDisconnected()
{
Console.WriteLine($"TCP protocol client disconnected the session with Id '{Id}'");
// Setup and asynchronously wait for the reconnect timer
_reconnectTimer?.Change(TimeSpan.FromSeconds(1), Timeout.InfiniteTimeSpan);
Disconnected?.Invoke();
}
public delegate void ReceivedHandler(byte[] buffer, long offset, long size);
public event ReceivedHandler Received = (buffer, offset, size) => {};
protected override void OnReceived(byte[] buffer, long offset, long size)
{
Received?.Invoke(buffer, offset, size);
}
protected override void OnError(SocketError error)
{
Console.WriteLine($"TCP protocol client caught a socket error: {error}");
}
#region IDisposable implementation
// Disposed flag.
private bool _disposed;
protected override void Dispose(bool disposingManagedResources)
{
if (!_disposed)
{
if (disposingManagedResources)
{
// Dispose managed resources here...
StopReconnectTimer();
}
// Dispose unmanaged resources here...
// Set large fields to null here...
// Mark as disposed.
_disposed = true;
}
// Call Dispose in the base class.
base.Dispose(disposingManagedResources);
}
// The derived class does not have a Finalize method
// or a Dispose method without parameters because it inherits
// them from the base class.
#endregion
}
public class SimpleProtoClient : Client, ISenderListener, IReceiverListener, IDisposable
{
private readonly TcpProtoClient _tcpProtoClient;
public Guid Id => _tcpProtoClient.Id;
public bool IsConnected => _tcpProtoClient.IsConnected;
public SimpleProtoClient(string address, int port)
{
_tcpProtoClient = new TcpProtoClient(address, port);
_tcpProtoClient.Connected += OnConnected;
_tcpProtoClient.Disconnected += OnDisconnected;
_tcpProtoClient.Received += OnReceived;
ReceivedResponse_DisconnectRequest += HandleDisconnectRequest;
ReceivedResponse_SimpleResponse += HandleSimpleResponse;
ReceivedResponse_SimpleReject += HandleSimpleReject;
ReceivedResponse_SimpleNotify += HandleSimpleNotify;
}
private void DisposeClient()
{
_tcpProtoClient.Connected -= OnConnected;
_tcpProtoClient.Connected -= OnDisconnected;
_tcpProtoClient.Received -= OnReceived;
ReceivedResponse_DisconnectRequest -= HandleDisconnectRequest;
ReceivedResponse_SimpleResponse -= HandleSimpleResponse;
ReceivedResponse_SimpleReject -= HandleSimpleReject;
ReceivedResponse_SimpleNotify -= HandleSimpleNotify;
_tcpProtoClient.Dispose();
}
public bool ConnectAndStart() { return _tcpProtoClient.ConnectAndStart(); }
public bool DisconnectAndStop() { return _tcpProtoClient.DisconnectAndStop(); }
public bool Reconnect() { return _tcpProtoClient.Reconnect(); }
private bool _watchdog;
private Thread _watchdogThread;
public bool StartWatchdog()
{
if (_watchdog)
return false;
Console.WriteLine("Watchdog thread starting...");
// Start the watchdog thread
_watchdog = true;
_watchdogThread = new Thread(WatchdogThread);
Console.WriteLine("Watchdog thread started!");
return true;
}
public bool StopWatchdog()
{
if (!_watchdog)
return false;
Console.WriteLine("Watchdog thread stopping...");
// Stop the watchdog thread
_watchdog = false;
_watchdogThread.Join();
Console.WriteLine("Watchdog thread stopped!");
return true;
}
public static void WatchdogThread(object obj)
{
var instance = obj as SimpleProtoClient;
if (instance == null)
return;
try
{
// Watchdog loop...
while (instance._watchdog)
{
var utc = DateTime.UtcNow;
// Watchdog the client
instance.Watchdog(utc);
// Sleep for a while...
Thread.Sleep(1000);
}
}
catch (Exception e)
{
Console.WriteLine($"Config client watchdog thread terminated: {e}");
}
}
#region Connection handlers
public delegate void ConnectedHandler();
public event ConnectedHandler Connected = () => {};
private void OnConnected()
{
// Reset FBE protocol buffers
Reset();
Connected?.Invoke();
}
public delegate void DisconnectedHandler();
public event DisconnectedHandler Disconnected = () => {};
private void OnDisconnected()
{
Disconnected?.Invoke();
}
public long OnSend(byte[] buffer, long offset, long size)
{
return _tcpProtoClient.SendAsync(buffer, offset, size) ? size : 0;
}
public void OnReceived(byte[] buffer, long offset, long size)
{
Receive(buffer, offset, size);
}
#endregion
#region Protocol handlers
private void HandleDisconnectRequest(DisconnectRequest request) { Console.WriteLine($"Received: {request}"); _tcpProtoClient.DisconnectAsync(); }
private void HandleSimpleResponse(SimpleResponse response) { Console.WriteLine($"Received: {response}"); }
private void HandleSimpleReject(SimpleReject reject) { Console.WriteLine($"Received: {reject}"); }
private void HandleSimpleNotify(SimpleNotify notify) { Console.WriteLine($"Received: {notify}"); }
#endregion
#region IDisposable implementation
// Disposed flag.
private bool _disposed;
// Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposingManagedResources)
{
// The idea here is that Dispose(Boolean) knows whether it is
// being called to do explicit cleanup (the Boolean is true)
// versus being called due to a garbage collection (the Boolean
// is false). This distinction is useful because, when being
// disposed explicitly, the Dispose(Boolean) method can safely
// execute code using reference type fields that refer to other
// objects knowing for sure that these other objects have not been
// finalized or disposed of yet. When the Boolean is false,
// the Dispose(Boolean) method should not execute code that
// refer to reference type fields because those objects may
// have already been finalized."
if (!_disposed)
{
if (disposingManagedResources)
{
// Dispose managed resources here...
DisposeClient();
}
// Dispose unmanaged resources here...
// Set large fields to null here...
// Mark as disposed.
_disposed = true;
}
}
#endregion
}
class Program
{
static void Main(string[] args)
{
// Simple protocol server address
string address = "127.0.0.1";
if (args.Length > 0)
address = args[0];
// Simple protocol server port
int port = 4444;
if (args.Length > 1)
port = int.Parse(args[1]);
Console.WriteLine($"Simple protocol server address: {address}");
Console.WriteLine($"Simple protocol server port: {port}");
Console.WriteLine();
// Create a new simple protocol chat client
var client = new SimpleProtoClient(address, port);
// Connect the client
Console.Write("Client connecting...");
client.ConnectAndStart();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Disconnect the client
if (line == "!")
{
Console.Write("Client disconnecting...");
client.Reconnect();
Console.WriteLine("Done!");
continue;
}
// Send request to the simple protocol server
SimpleRequest request = SimpleRequest.Default;
request.Message = line;
var response = client.Request(request).Result;
// Show string hash calculation result
Console.WriteLine($"Hash of '{line}' = 0x{response.Hash:X8}");
}
// Disconnect the client
Console.Write("Client disconnecting...");
client.DisconnectAndStop();
Console.WriteLine("Done!");
}
}
}