Skip to content

Quick and simple implementation of TcpClient and TcpListener that implements several features for structured, orderly, and secure data exchange.

License

Notifications You must be signed in to change notification settings

mnwachukwu/TM14.Networking

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TM14.Networking Quick Help

This library contains wrapper classes around the System.Net.Sockets.TcpClient and System.Net.Sockets.TcpListener classes to make rapid use of those classes to transfer data between applications.

In order to make quick usage of the data transfer functionality, a Packet class has been included so that structured data contracts can be created between a client and server program.

A PacketBuffer class is included to ensure every packet is sent and received reliably, with no malformed parts being parsed.

It is written against .Net Standard 2.0 so that it can be used in your .Net Framework, .Net Core, and .Net 5 applications.

This library makes use of JSON and as such, utilizes Newtonsoft.Json as a dependency from NuGet.

There is a detailed documentation website if you need more guidance. There, you can find a full guide on the Classes and Events this library provides.

This project is open source on Github, if you're interested in looking at the code base. You can also find a download link to the .dll under the Releases section on Github if you prefer to just use the compiled assembly in your project.

Copyright © Studio TM14

Example Usage

Note: You must properly configure the SecretKey of your application(s) before the code in this example will work. Refer to the Security section of this documentation (below this section) for more information.

Client

Initialize

// Initialize the TcpClient somewhere
var tcpClient = new TcpClient(ServerIp, ServerPort);
tcpClient.HasPacket += TcpClient_HasPacket;
tcpClient.Connect();

Sending data

// Example method to build and send packets of data
public static void SendData(string packetHeader, params string[] packetData)
{
    var packet = new Packet(packetHeader, packetData);
    tcpClient.SendData(packet);
}

Receiving data

// Example TcpClient_HasPacket event handler
private static void TcpClient_HasPacket(object sender, HasPacketEventArgs e)
{
    HandlePacket(e.Packet);
}

// Example HandlePacket method (called from the event handler)
private static void HandlePacket(Packet packet)
{
    switch (packet.Header.ToLower())
    {
        case "a data header here":
            // Do something with the packet data
            break;
    }
}

Server

Initialize

// Initialize the TcpServer somewhere
var tcpServer = new TcpServer(ServerIp, ServerPort);
tcpServer.HasPacket += TcpServer_HasPacket;
tcpServer.StartListener();

Sending data

// Example method to build and send packets of data
public static void SendData(System.Net.Sockets.TcpClient client, string packetHeader, params string[] packetData)
{
    var packet = new Packet(packetHeader, packetData);
    tcpServer.SendDataTo(client, packet);
}

Receiving data

// Example TcpServer_HasPacket event handler
private static void TcpServer_HasPacket(object sender, HasPacketEventArgs e)
{
    HandlePacket(e.Sender, e.Packet);
}

// Example HandlePacket method (called from the event handler)
private static void HandlePacket(System.Net.Sockets.TcpClient client, Packet packet)
{
    switch (packet.Header.ToLower())
    {
        case "a data header here":
            // Do something with the packet data
            break;
    }
}

Security

Setting a SecretKey

Within the DataTransferProtocol class, there is a member called SecretKey intended to secure trafic created by this library via encryption. It can't be null or empty and it must be able to be converted from a base 64 string to a byte[32].

SecretKey can easily be set by calling the DataTransferProtocol.SetSecretKey() method.

SecretKey is defined as an internal static string so that you may use external secure mechanisms to set the value. It could also be defined as an internal const string so that you can set it in code, rather than during run-time. However, unless your application is obfuscated (encrypting or hiding away constant values), this compromises the network security of your application. This approach also breaks the DataTransferProtocol.SetSecretKey() method, but it can just be deleted.

The client and server applications implementing this library must have the same SecretKey when communicating with each other or else, they will not be able to decrypt each other's traffic.

Generating a SecretKey

If you're looking for an easy way to get a secret key to use that's compatible with this library, consider the following method.

public static void GenerateUsableKey()
{
    var key = AesHmacCrypto.NewKey();
    var keyString = Convert.ToBase64String(key);

    // You want to use the value of `keyString` as your SecretKey
    Console.WriteLine($"Key As String: {keyString}");
}

This method is not included in the library but, it can be implemented into your copy of the library or, retooled to be used outside of the library in order to generate a secret key for your application.

Handling Exceptions

As a philosophy, I don't think that exceptions in the networking layer should crash an application. Especially not a server application. This library will "swallow" exceptions thrown by it while handling data, disconnecting clients as needed.

However, you may wish to utilize the exceptions that are thrown by this library. You may want to log errors, or use the exception to break code execution. If this is desired, you can hook into an event either on the client or the server (or both) called HasCaughtException. This event, when raised, exposes any exceptions thrown by the networking library during data transmission.

Client Example

var tcpClient = new TcpClient(ServerIp, ServerPort);
tcpClient.HasCaughtException += TcpClient_HasCaughtException;

private static void TcpClient_HasCaughtException(object sender, HasCaughtExceptionEventArgs e)
{
    Console.WriteLine($"{e.TimeStamp:g} {e.Exception.Message}");
    throw e.Exception;
}

Server Example

var tcpServer = new TcpServer(ServerIp, ServerPort);
tcpServer.HasCaughtException += TcpServer_HasCaughtException;

private static void TcpServer_HasCaughtException(object sender, HasCaughtExceptionEventArgs e)
{
    Console.WriteLine($"{e.TimeStamp:g} {e.Exception.Message}");
    throw e.Exception;
}

About

Quick and simple implementation of TcpClient and TcpListener that implements several features for structured, orderly, and secure data exchange.

Topics

Resources

License

Stars

Watchers

Forks

Languages