.NetCoreServer is a dotnet server solution to use where you want. Server have config.json file to specific some parameters and 2 clients to use the server as normal dummy client and as admin client.
How to start:
Config file (config.json)
The server need a minimum of configurations to start. All configurations are includes this file.
The following lines shows the configurations file options:
{
"SERVER_IP": "YOUR SERVER IP HERE. DEFAULT localhost",
"SERVER_PORT": "YOUR SERVER PORT HERE. DEFAULT 4044",
"DEBUG_MODE": "SHOW OR HIDE THE SERVER MENU {true: false}"
"PATH_LOG_FOLDER": "PATH TO YOUR LOGS FILES DIRECTORY ( DEFAULT SERVER folder/serverlogs)"
}
In the configurations if want default just set the value to empty valor.
{
"SERVER_IP": "",
"SERVER_PORT": "",
"DEBUG_MODE": "true"
"PATH_LOG_FOLDER": ""
}
This is the minimum configuration to server (To work in localhost).
If some options are wrong, server will thrown a exception.
The Server.cs class need some models to work. All models are stored in Models folder. If want some extra function or include a new model just put here and call in in the ListenClient(object o) method from Server.cs.
Example if you want to receive a option class make your model and at the second do while include it like this:
private void ListenClient(object o)
{
Socket socket = (Socket)o;
object received;
do
{
//Wait for a user to client and start socket and threads
}
} while (!(received is User));
do
{
received = Receive(socket);
//Other object type stuff
if (received is Option option)
{
//Do Option stuff that u need
continue;
}
} while (true);
socket.Close();
}
All models you makes must be in the same namespace (SharedNameSpace) and include the flag [Serializable] Example below.
using System;
namespace SharedNameSpace
{
/// <summary>
/// Example Model to option
/// </summary>
[Serializable]
class Option
{
public var someVariableThatUNeed;
public Option(Var someVariableThatUNeed)
{
this.someVariableThatUNeed= someVariableThatUNeed;
}
}
}
To build the database can make a new SQLite database with this structure:
-- TABLE
CREATE TABLE "Users" (
"Id" TEXT NOT NULL CONSTRAINT "PK_Users" PRIMARY KEY,
"Name" TEXT NOT NULL,
"IsAdmin" INTEGER NOT NULL
);
CREATE TABLE "__EFMigrationsHistory" (
"MigrationId" TEXT NOT NULL CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY,
"ProductVersion" TEXT NOT NULL
);
Or use the Migration class. In Visual Studio open the console and run the following command:
update-Database
For delete the migration use:
remove-migration
To update the migration go to /Migrations/20200911090205_InitialCreate.cs and write your tables in the Up method.
We have a SqLiteOperator in the server (Server/Database/SqLiteOperator.cs) to manage SQLite databases. U can do all u want with databases here, I just include a Users CRUD. If need more info about program new functionalitys check this link.
When server aren't in debug mode will check if user exist in the database.
To manage database put server in debug mode (Remember config file) and use the Manage database option in menu.
GESTIONAR BASE DE DATOS
=====================================
1. Listar agentes en la base de datos
2. Buscar agente
3. Añadir nuevo agente
4. Modificar agente
5. Eliminar agente
ESC. Volver al menú principal
Seleccione una opción.
Translation:
- List all users
- Find user
- Add user
- Modify user
- Delete user
The list is in MariaDB style.
+-------------------------------------------+
| | ID | NAME | IS ADMIN |
+-------------------------------------------+
| 001 | ADMIN | ADMIN | True |
+-------------------------------------------+
| 002 | admin | admin | True |
+-------------------------------------------+
| 003 | asd | asd | False |
+-------------------------------------------+
| 004 | noadmin | noadmin | False |
+-------------------------------------------+
| 005 | test | test | True |
+-------------------------------------------+
The SqLiteOperator is a Singleton.
Should be called SqLiteOperator.GetInstance().method();
Server communications are based on serialized objects. For this purpose in /Utils/Serialization.cs have a Serialization class. The class should serialize/deserializate all send/received objects.
When u deserializate a received item need be in the same executing assembly. If don't, this class will throw a SerializationError. This class make the same executing assembly:
public class CurrentAssemblyDeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
return Type.GetType(string.Format("{0}, {1}", typeName, Assembly.GetExecutingAssembly().FullName));
}
}
And in the public static object Deserializate(byte[] data) method when create the BinaryFormatter, set the Binder like this:
BinaryFormatter formatter = new BinaryFormatter
{
Binder = new CurrentAssemblyDeserializationBinder()
};
This class implements the Singleton pattern.
The Server.cs use a external configuration, for read this settings use the interface IConfiguration and IConfigurationBuilder. This two dependencies are includes in nuget package Microsoft.Extensions.Configuration . Link here.
As the configuration is in json format we need install other nuget package : Microsoft.Extensions.Configuration.Json for extend the class ConfigurationBuilder : AddJsonFile and AddJsonStream. Link here.
The code line is this:
static readonly IConfiguration config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("config.json").Build();
From this configuration file this class use the key/value collections: SERVER_IP, SERVER_PORT and DEBUG_MODE.
Server.cs have two thread-safe collections to store agents and admins called ConcurrentDictionary , one socket for listen all clients and one thread to create new instances when client connect.
When call Server.cs for first time this is the method execution for start listen clients:
- GetInstance()
- If server instance is null:
server = new Server - Return server instance
- If server instance is null:
- StartServer(ErrorDelegate errorDelegate)
- Bind delegates to show errors
- Try parse the config SERVER_IP and SERVER_PORT values
- If fail thrown format exception
- Makes the socket and bind to SERVER_IP:SERVER_PORT
- Start listen.
- Make the SqLiteOperator instance.
- Make a new thread for wait clients. (This thread do Listen method)
- create the two collections to store clients
- Put IsServerRunning to true
- Listen (From the new thread)
- Create a Socket "client"
- Enter in infinite loop (while server running)
- Wait for a client doing socket.Accept()
- When client connect to server socket makes a new thread (listenClient) and point on ListenClient method.
Thread listenClient = new Thread(ListenClient); - Start the Thread passing the socket to method.
listenClient.Start(client);
- Check IsServerRunning to break the loop
When server start and ListenClient method aren´t in debug mode, need check if user exist in database.
Here have a pseudocode method example:
