Проблема при совместной записи ModbusClient и ModbusServer

О Кодексе

Я использую EasyModbus Nugetв приложении C# Window Form. Я пытаюсь получить измененное значение адреса регистра временного хранения через RTU(обновление в реальном времени), используяModbusServer.

Ниже код подключения к серверу.

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

Код ниже извлекает значение адреса, указанного под регистром временного хранения.

client.ReadHoldingRegisters(10001, 1);

Пока все работает отлично.

Я читал об обновлениях в реальном времени в EasyModbus. Я нашел эту ссылку, которая может автоматически отправлять измененное значение регистра хранения обработчику четности.

Теперь у меня есть код ниже:

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 ответа

Ваша проблема не такая серьезная и ваша основная проблема в этой строке

ser.Listen();

потому что ваш предыдущий серверный сокет все еще привязан.

давайте посмотрим, когда сокет прослушивания привязан?

очевидная причина в том, что когда ваш слушающий сокет отправляет / принимает пакеты, но в редких случаях это происходит, когда ОС НЕ находится в идеальном состоянии (100 % использование процессора и т.д.), тогда для освобождения сокета сервера может потребоваться минута. в этом состоянии, когда вы снова запустите свой сервер, исключение

Обычно разрешается только одно использование каждого адреса сокета (протокол / сетевой адрес / порт).

происходит. потому что, как я уже сказал, предыдущий серверный сокет еще не был выпущен.

Решение

использование разных портов для разных сокетов сервера

или

используйте только один серверный сокет, который запускается только один раз, и проверьте, подключен он или нет.

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

Кажется, у вас уже есть сервер на порту и вы пытаетесь добавить еще один. Попробуйте следующий код:

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 перед AddServerвы получите еще одну ошибку. Добавьте один сервер, а затем добавьте любое количество клиентов. Каждый клиент записывает регистр временного хранения, и связанное событие запускается с сообщением, подобным этому:

Другие вопросы по тегам