Issue while writing ModbusClient and ModbusServer together

风格不统一 提交于 2020-07-08 09:25:34

问题


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?


回答1:


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();



回答2:


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
    }
}

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:



来源:https://stackoverflow.com/questions/57984190/issue-while-writing-modbusclient-and-modbusserver-together

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!