Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue while writing ModbusClient and ModbusServer together

About the Code

I am using EasyModbus Nuget in C# Window Form Application. I am trying to fetch the changed Holding Register's Address Value through RTU(Real Time Update) using ModbusServer.

Below code connect to server.

void Connect() {
    ModbusClient client = null;
    client = new ModbusClient("IP Address", 502);
    client.Connect();
}

Below code fetches the value of address given below Holding Register.

client.ReadHoldingRegisters(10001, 1);

So far, everything works perfectly.

I was reading about reading about Real Time Updates in EasyModbus. I found this link that can send the changed value of holding register automatically to the even handler.

Now, I have below code:

void Connect() {
    ModbusServer ser = new ModbusServer();
    ser.Port = Convert.ToInt32(Settings.Default.Port);
    ser.Listen();
    ser.HoldingRegistersChanged += Ser_HoldingRegistersChanged;

    ModbusClient client = null;
    client = new ModbusClient("IP Address", 502);
    client.Connect();
}


private void Ser_HoldingRegistersChanged(int register, int numberOfRegisters)
{
}

When I run it, I get below error.

Only one usage of each socket address (protocol/network address/port) is normally permitted

This error is occurring because I added the ModbusServer code.

Can you please suggest why this is happening?

like image 757
Pankaj Avatar asked Sep 18 '19 02:09

Pankaj


2 Answers

Your problem isn't so serious and your main problem in this line

ser.Listen();

because your previous server socket is still in bound.

let's take a looks when a listen socket is in bound ?

obvious reason is when your listening socket send/receive packets but in rare conditions it happens when OS is NOT in ideal condition(100 % cpu usage and etc) then Releasing server socket might takes a minute to be released. in this condition when you run your server again the exception

Only one usage of each socket address (protocol/network address/port) is normally permitted

happens.because , as i said before the previous server socket was not released yet.

Solution is

using different ports for different server sockets

or

use only one server socket which is initiated only once and check if it's connected or not.

// create the socket
public static Socket listenSocket = new Socket(AddressFamily.InterNetwork, 
                                        SocketType.Stream,
                                        ProtocolType.Tcp);

// bind the listening socket to the port
IPAddress hostIP = (Dns.Resolve(IPAddress.Any.ToString())).AddressList[0];
IPEndPoint ep = new IPEndPoint(hostIP, port);
if(!listenSocket.IsBound){
  listenSocket.Bind(ep);     
  // start listening
  listenSocket.Listen(backlog);
}
// connect client 
ModbusClient client = null;
client = new ModbusClient(hostIP , port);
client.Connect();
like image 192
A Farmanbar Avatar answered Oct 11 '22 00:10

A Farmanbar


It seems you already have a server on the port and you try to add one more. Try the code below:

public partial class Form1 : Form
{
    private int register = 0;
    private readonly int port = 502;
    private readonly List<ModbusServer> servers = new List<ModbusServer>();
    private readonly List<ModbusClient> clients = new List<ModbusClient>();

    public Form1()
    {
        InitializeComponent();
        AppDomain.CurrentDomain.FirstChanceException +=
            (sender, e) => MessageBox.Show(e.Exception.Message);
    }

    private void Foo(object sender, ThreadExceptionEventArgs e)
    {
        MessageBox.Show(e.Exception.Message);
    }

    private void Ser_HoldingRegistersChanged(int register, int numberOfRegisters) =>
        MessageBox.Show($"register: {register}, numberOfRegisters: {numberOfRegisters}");

    private void AddServer_Click(object sender, EventArgs e) =>
        AddServerMethod();

    private void AddClient_Click(object sender, EventArgs e) =>
        AddClientMethod();

    private void AddServerMethod()
    {
        var server = new ModbusServer { Port = port };
        server.Listen();
        server.HoldingRegistersChanged += Ser_HoldingRegistersChanged;
        servers.Add(server);
        MessageBox.Show("Server added.");
        server.holdingRegisters[0] = 11; // register is changed, but no event is fired
    }

    private void AddClientMethod()
    {
        var client = new ModbusClient("127.0.0.1", port);
        client.Connect();
        clients.Add(client);
        MessageBox.Show("Client added.");
        client.WriteSingleRegister(register++, 11); // event is fired
    }
}

enter image description here

If you click AddServer more than once you get the error you described. Btw, if you click AddClient before AddServer you get another error. Add one server and then add any number of clients. Each client writes a holding register and related event is fired with a message like this:

enter image description here

like image 21
Alex Avatar answered Oct 11 '22 01:10

Alex