Added a socket client

This commit is contained in:
Rene Schwarz
2021-08-07 01:01:17 +02:00
parent 58524a9514
commit f8f28984a5
62 changed files with 1320 additions and 174 deletions

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Server_Dashboard_Socket {
/// <summary>
/// Client Socket
/// </summary>
/// <typeparam name="TProtocol">The Protocol type, either JsonMessageProtocol or XmlMessageProtocol</typeparam>
/// <typeparam name="TMessageType">The message type, either JObject or XDocument</typeparam>
public class ClientChannel<TProtocol, TMessageType> : SocketChannel<TProtocol, TMessageType>
where TProtocol : Protocol<TMessageType>, new(){
/// <summary>
/// Connect to the socket async
/// </summary>
/// <param name="endpoint">An endpoint with an IP address and port</param>
/// <returns></returns>
public async Task ConnectAsync(IPEndPoint endpoint) {
//Creates a new Socket
var socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//Connects to the socket
await socket.ConnectAsync(endpoint).ConfigureAwait(false);
//Attach the socket to a network stream
Attach(socket);
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Dashboard_Socket {
/// <summary>
/// Generic Channel class that handles the connection and message sending / receiving
/// Inherits IDisposable to correctly cut the connection to the server
/// </summary>
/// <typeparam name="TProtocol">The Protocol type, either JsonMessageProtocol or XmlMessageProtocol</typeparam>
/// <typeparam name="TMessageType">The message type, either JObject or XDocument</typeparam>
public abstract class SocketChannel<TProtocol, TMessageType> : IDisposable
where TProtocol : Protocol<TMessageType>, new() {
protected bool isDisposable = false;
NetworkStream networkStream;
readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
readonly TProtocol protocol = new TProtocol();
Func<TMessageType, Task> messageCallback;
/// <summary>
/// Attaches the socket to a network stream that owns the socket
/// if the network stream goes down it takes the socket with it!
/// </summary>
/// <param name="socket">A Socket</param>
public void Attach(Socket socket) {
networkStream = new NetworkStream(socket, true);
_ = Task.Run(ReceiveLoop, cancellationTokenSource.Token);
}
/// <summary>
/// Takes a function with a message and sets the private member to the functions value
/// </summary>
/// <param name="callbackHandler"></param>
public void OnMessage(Func<TMessageType, Task> callbackHandler) => messageCallback = callbackHandler;
/// <summary>
/// Makes sure to close the socket
/// </summary>
public void Close() {
cancellationTokenSource.Cancel();
networkStream?.Close();
}
/// <summary>
/// Sends the message async
/// </summary>
/// <typeparam name="T">Anything as message, e.g. object or string</typeparam>
/// <param name="message">The message</param>
/// <returns></returns>
public async Task SendAsync<T>(T message) => await protocol.SendAsync(networkStream, message).ConfigureAwait(false);
/// <summary>
/// Checks for received messages
/// </summary>
/// <returns>received message</returns>
protected virtual async Task ReceiveLoop() {
while (!cancellationTokenSource.Token.IsCancellationRequested) {
var msg = await protocol.ReceiveAsync(networkStream).ConfigureAwait(false);
await messageCallback(msg).ConfigureAwait(false);
}
}
/// <summary>
/// Deconstructor sets Dispose to false
/// </summary>
~SocketChannel() => Dispose(false);
/// <summary>
/// Sets dispose to true
/// </summary>
public void Dispose() => Dispose(true);
/// <summary>
/// Disposes open sockets
/// </summary>
/// <param name="isDisposing">Is it currently disposing stuff?</param>
protected void Dispose(bool isDisposing) {
//If its not disposable
if (!isDisposable) {
//Set disposable to true
isDisposable = true;
//Close the socket
Close();
//If its closed, dispose it
networkStream?.Dispose();
//Wait with the garbage collection untill the disposing is done
if (isDisposing)
GC.SuppressFinalize(this);
}
}
}
}