public async void ServerHandlesRequestFire() { // Arrange var serialPort = new FakeSerialPort(); var server = new ModbusRtuServer(unitIdentifier: 1); server.Start(serialPort); var client = new ModbusRtuClient(); client.Connect(serialPort); await Task.Run(() => { var data = Enumerable.Range(0, 20).Select(i => (float)i).ToArray(); var sw = Stopwatch.StartNew(); var iterations = 10000; for (int i = 0; i < iterations; i++) { client.WriteMultipleRegisters(0, 0, data); } var timePerRequest = sw.Elapsed.TotalMilliseconds / iterations; _logger.WriteLine($"Time per request: {timePerRequest * 1000:F0} us. Frequency: {1 / timePerRequest * 1000:F0} requests per second."); client.Close(); }); server.Stop(); // Assert }
static void DoServerWork(ModbusRtuServer server) { var random = new Random(); // Option A: normal performance version, more flexibility /* get buffer in standard form (Span<short>) */ var registers = server.GetHoldingRegisters(); registers.SetLittleEndian(address: 5, random.Next()); // Option B: high performance version, less flexibility /* interpret buffer as array of bytes (8 bit) */ var byte_buffer = server.GetHoldingRegisterBuffer <byte>(); byte_buffer[20] = (byte)(random.Next() >> 24); /* interpret buffer as array of shorts (16 bit) */ var short_buffer = server.GetHoldingRegisterBuffer <short>(); short_buffer[30] = (short)(random.Next(0, 100) >> 16); /* interpret buffer as array of ints (32 bit) */ var int_buffer = server.GetHoldingRegisterBuffer <int>(); int_buffer[40] = random.Next(0, 100); }
/// <summary> /// 启动仿真服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void but_open_server_Click(object sender, EventArgs e) { try { if (txt_content.Text.Contains("小技巧")) { txt_content.Text = string.Empty; } var PortName = cb_portNameSend_server.Text.ToString(); var BaudRate = int.Parse(cb_baudRate.Text.ToString()); var DataBits = int.Parse(txt_dataBit.Text.ToString()); var StopBits = (StopBits)int.Parse(txt_stopBit.Text.ToString()); var parity = cb_parity.SelectedIndex == 0 ? Parity.None : (cb_parity.SelectedIndex == 1 ? Parity.Odd : Parity.Even); server?.Stop(); server = new ModbusRtuServer(PortName, BaudRate, DataBits, StopBits, parity); server.Start(); AppendText("开启仿真服务"); but_server_open.Enabled = false; but_server_close.Enabled = true; cb_portNameSend_server.Enabled = false; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
static void DoServerWork(ModbusRtuServer server) { var random = new Random(); // interpret buffer as array of bytes (8 bit) var byte_buffer = server.GetHoldingRegisterBuffer <byte>(); byte_buffer[20] = (byte)(random.Next() >> 24); // interpret buffer as array of shorts (16 bit) var short_buffer = server.GetHoldingRegisterBuffer <short>(); short_buffer[30] = (short)(random.Next(0, 100) >> 16); // interpret buffer as array of ints (32 bit) var int_buffer = server.GetHoldingRegisterBuffer <int>(); int_buffer[40] = random.Next(0, 100); }
static async Task Main(string[] args) { /* Modbus RTU uses a COM port for communication. Therefore, to run * this sample, you need to make sure that there are real or virtual * COM ports available. The easiest way is to install one of the free * COM port bridges available in the internet. That way, the Modbus * server can connect to e.g. COM1 which is virtually linked to COM2, * where the client is connected to. * * When you only want to use the client and communicate to an external * Modbus server, simply remove all server related code parts in this * sample and connect to real COM port using only the client. */ /* define COM ports */ var serverPort = "COM1"; var clientPort = "COM2"; /* prepare dependency injection */ var services = new ServiceCollection(); ConfigureServices(services); /* create types */ var provider = services.BuildServiceProvider(); var loggerFactory = provider.GetRequiredService <ILoggerFactory>(); var serverLogger = loggerFactory.CreateLogger("Server"); var clientLogger = loggerFactory.CreateLogger("Client"); /* create Modbus RTU server and client */ var server = new ModbusRtuServer(unitIdentifier: 1); var client = new ModbusRtuClient(); /* run Modbus RTU server */ var cts = new CancellationTokenSource(); var task_server = Task.Run(async() => { server.Start(serverPort); serverLogger.LogInformation("Server started."); while (!cts.IsCancellationRequested) { // lock is required to synchronize buffer access between this application and the Modbus client lock (server.Lock) { DoServerWork(server); } // update server buffer content once per second await Task.Delay(TimeSpan.FromSeconds(1)); } server.Dispose(); }, cts.Token); /* run Modbus RTU client */ var task_client = Task.Run(() => { client.Connect(clientPort); try { DoClientWork(client, clientLogger); } catch (Exception ex) { clientLogger.LogError(ex.Message); } client.Close(); Console.WriteLine("Tests finished. Press any key to continue."); Console.ReadKey(true); }); // wait for client task to finish await task_client; // stop server cts.Cancel(); await task_server; server.Stop(); serverLogger.LogInformation("Server stopped."); }
static async Task Main(string[] args) { /* Modbus RTU uses a COM port for communication. Therefore, to run * this sample, you need to make sure that there are real or virtual * COM ports available. The easiest way is to install one of the free * COM port bridges available in the internet. That way, the Modbus * server can connect to e.g. COM1 which is virtually linked to COM2, * where the client is connected to. * * When you only want to use the client and communicate to an external * Modbus server, simply remove all server related code parts in this * sample and connect to real COM port using only the client. */ /* define COM ports */ var serverPort = "COM1"; var clientPort = "COM2"; /* create logger */ var loggerFactory = LoggerFactory.Create(loggingBuilder => { loggingBuilder.SetMinimumLevel(LogLevel.Debug); loggingBuilder.AddConsole(); }); var serverLogger = loggerFactory.CreateLogger("Server"); var clientLogger = loggerFactory.CreateLogger("Client"); /* create Modbus RTU server */ using var server = new ModbusRtuServer(unitIdentifier: 1) { // see 'RegistersChanged' event below EnableRaisingEvents = true }; /* subscribe to the 'RegistersChanged' event (in case you need it) */ server.RegistersChanged += (sender, registerAddresses) => { // the variable 'registerAddresses' contains a list of modified register addresses }; /* create Modbus RTU client */ var client = new ModbusRtuClient(); /* run Modbus RTU server */ var cts = new CancellationTokenSource(); var task_server = Task.Run(async() => { server.Start(serverPort); serverLogger.LogInformation("Server started."); while (!cts.IsCancellationRequested) { // lock is required to synchronize buffer access between this application and the Modbus client lock (server.Lock) { DoServerWork(server); } // update server register content once per second await Task.Delay(TimeSpan.FromSeconds(1)); } }, cts.Token); /* run Modbus RTU client */ var task_client = Task.Run(() => { client.Connect(clientPort); try { DoClientWork(client, clientLogger); } catch (Exception ex) { clientLogger.LogError(ex.Message); } client.Close(); Console.WriteLine("Tests finished. Press any key to continue."); Console.ReadKey(true); }); // wait for client task to finish await task_client; // stop server cts.Cancel(); await task_server; server.Stop(); serverLogger.LogInformation("Server stopped."); }