Apollo3zehn / FluentModbus

Lightweight and fast client and server implementation of the Modbus protocol (TCP/RTU).
MIT License
188 stars 69 forks source link

ModbusTCPServer view connected clients #116

Closed GREEFA-gvanos closed 1 month ago

GREEFA-gvanos commented 2 months ago

Hello,

First of all i'm using the library and think it is a great implementation. However i would like to have the following posibilities:

Currently it is possible to view the amount of connected clients via the ConnectionCount Property it would be nice to also see for each connected client what the IP address of that client is.

Maybe an event on the client connection is also good enought. for examlpe:

Please let me know if something like this is possible or planned for the future.

Greetings Gerrit van Os

GREEFA-gvanos commented 1 month ago

After looking into the ITCPClientProvider interface i could build my own implementation for this and add the connected client features i was asking for so this issue is not relevant anymore

Apollo3zehn commented 1 month ago

Sorry for not answering yet. Glad you found a solution.

GREEFA-gvanos commented 1 month ago

I will post the code i used below, it is a bit of a specific version for my application but maybe it could be usefull for someone else in the future. There are some tricky parts in this code, for example me assuming the remote endpoint is an "IPEndPoint" but it worked for now

public class TcpClientProvider : ITcpClientProvider
{
    private TcpListener _tcpListener;
    private List<KeyValuePair<string, TcpClient>> _connectedClients = [];

    public TcpClientProvider(IPEndPoint endPoint)
    {
        _tcpListener = new TcpListener(endPoint);
        _tcpListener.Start();
    }

    public List<string> ConnectedClientIPs => _connectedClients.Select(c => c.Key).ToList();
    public event EventHandler ClientDisconnected;
    public event EventHandler ClientConnected;

    public Task<TcpClient> AcceptTcpClientAsync()
    {
        Task<TcpClient> client = _tcpListener.AcceptTcpClientAsync();
        string ipAddress = ((IPEndPoint)client.Result.Client.RemoteEndPoint).Address.ToString();

        BasicLogger.Trace($"TCPClientProvider: Client connected with IP: {ipAddress}");

        _connectedClients.Add(new(ipAddress, client.Result));
        ClientConnected?.Invoke(this, EventArgs.Empty);

        return client;
    }

    public void CheckConnectedClients()
    {
        List<KeyValuePair<string, TcpClient>> toRemove = [];
        foreach (KeyValuePair<string, TcpClient> client in _connectedClients)
        {
            if (!client.Value.Connected)
            {
                BasicLogger.Trace($"TCPClientProvider: Client disconnect with IP {client.Key}");
                toRemove.Add(client);
            }
        }

        foreach (KeyValuePair<string, TcpClient> clientToRemove in toRemove)
        {
            _connectedClients.Remove(clientToRemove);
            ClientDisconnected?.Invoke(this, EventArgs.Empty);
        }
    }
    public void Dispose()
    {
        _tcpListener.Dispose();
    }
}