一起编写ModbusClient和ModbusServer时出现问题

时间:2019-09-18 02:18:15

标签: c# modbus-tcp easy-modbus

关于守则

我在C#窗口表单应用程序中使用EasyModbus Nuget。我正在尝试使用ModbusServer通过RTU(实时更新)来获取更改的保留寄存器的地址值。

下面的代码连接到服务器。

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

下面的代码获取保留寄存器下面给出的地址值。

client.ReadHoldingRegisters(10001, 1);

到目前为止,一切正常。

我正在阅读有关EasyModbus中实时更新的信息。 I found this link that can send the changed value of holding register automatically to the even handler.

现在,我有以下代码:

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

运行时,出现以下错误。

  

每个套接字地址(协议/网络地址/端口)仅一种用法   通常是允许的

发生此错误是因为我添加了ModbusServer代码。

请问您为什么会这样?

2 个答案:

答案 0 :(得分:3)

您的问题不是很严重,这是您的主要问题

ser.Listen();

因为您以前的服务器套接字仍在绑定中。

让我们看一下侦听套接字绑定时的情况吗?

一个明显的原因是,当您的侦听套接字发送/接收数据包时,但在极少数情况下,它会在操作系统不处于理想状态(100%cpu使用率等)时发生,那么释放服务器套接字可能需要一分钟的时间才能释放。在这种情况下,当您再次运行服务器时

  

每个套接字地址(协议/网络地址/端口)仅一种用法   通常是允许的

happens.because,因为我在以前的服务器套接字尚未发布之前说过。

解决方案

为不同的服务器套接字使用不同的端口

仅使用一个仅启动一次的服务器套接字,并检查其是否已连接。

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

答案 1 :(得分:0)

似乎您的端口上已经有一台服务器,然后尝试再添加一台。尝试以下代码:

NSInteger i = 0;
CGSize statusBarSize = [UIApplication sharedApplication].windows[i].windowScene.statusBarManager.statusBarFrame.size;

enter image description here

如果您多次单击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 } } ,则会收到所描述的错误。顺便说一句,如果您在AddServer之前单击AddClient,则会收到另一个错误。添加一台服务器,然后添加任意数量的客户端。每个客户端写一个保持寄存器,并用以下消息触发相关事件:

enter image description here