1
0
mirror of https://github.com/zhaopeiym/IoTClient synced 2025-10-12 21:20:37 +08:00

update ModobusTcp demo

This commit is contained in:
BennyZhao 2019-10-15 10:24:58 +08:00
parent 1d604c9d68
commit 5a44588ba4
9 changed files with 935 additions and 192 deletions

View File

@ -83,16 +83,16 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ModBusTcp.cs">
<Compile Include="ModBusTcpForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ModBusTcp.Designer.cs">
<DependentUpon>ModBusTcp.cs</DependentUpon>
<Compile Include="ModBusTcpForm.Designer.cs">
<DependentUpon>ModBusTcpForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="ModBusTcp.resx">
<DependentUpon>ModBusTcp.cs</DependentUpon>
<EmbeddedResource Include="ModBusTcpForm.resx">
<DependentUpon>ModBusTcpForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>

391
IoTClient.Demo/ModBusTcpForm.Designer.cs generated Normal file
View File

@ -0,0 +1,391 @@
namespace IoTClient.Demo
{
partial class ModBusTcpForm
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.button1 = new System.Windows.Forms.Button();
this.but_open = new System.Windows.Forms.Button();
this.txt_ip = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.txt_port = new System.Windows.Forms.TextBox();
this.rd_short = new System.Windows.Forms.RadioButton();
this.txt_address = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.button3 = new System.Windows.Forms.Button();
this.txt_value = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.button4 = new System.Windows.Forms.Button();
this.txt_content = new System.Windows.Forms.TextBox();
this.txt_stationNumber = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.rd_bit = new System.Windows.Forms.RadioButton();
this.rd_ushort = new System.Windows.Forms.RadioButton();
this.rd_uint = new System.Windows.Forms.RadioButton();
this.rd_int = new System.Windows.Forms.RadioButton();
this.rd_ulong = new System.Windows.Forms.RadioButton();
this.rd_long = new System.Windows.Forms.RadioButton();
this.rd_double = new System.Windows.Forms.RadioButton();
this.rd_float = new System.Windows.Forms.RadioButton();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(548, 19);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(99, 23);
this.button1.TabIndex = 0;
this.button1.Text = "本地模拟服务";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// but_open
//
this.but_open.Location = new System.Drawing.Point(309, 18);
this.but_open.Name = "but_open";
this.but_open.Size = new System.Drawing.Size(75, 23);
this.but_open.TabIndex = 1;
this.but_open.Text = "连接";
this.but_open.UseVisualStyleBackColor = true;
this.but_open.Click += new System.EventHandler(this.button2_Click);
//
// txt_ip
//
this.txt_ip.Location = new System.Drawing.Point(37, 19);
this.txt_ip.Name = "txt_ip";
this.txt_ip.Size = new System.Drawing.Size(100, 21);
this.txt_ip.TabIndex = 2;
this.txt_ip.Text = "127.0.0.1";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(8, 24);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(29, 12);
this.label1.TabIndex = 3;
this.label1.Text = "IP";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(148, 24);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(41, 12);
this.label2.TabIndex = 4;
this.label2.Text = "端口:";
//
// txt_port
//
this.txt_port.Location = new System.Drawing.Point(193, 19);
this.txt_port.Name = "txt_port";
this.txt_port.Size = new System.Drawing.Size(100, 21);
this.txt_port.TabIndex = 5;
this.txt_port.Text = "502";
//
// rd_short
//
this.rd_short.AutoSize = true;
this.rd_short.Checked = true;
this.rd_short.Location = new System.Drawing.Point(70, 23);
this.rd_short.Name = "rd_short";
this.rd_short.Size = new System.Drawing.Size(53, 16);
this.rd_short.TabIndex = 6;
this.rd_short.TabStop = true;
this.rd_short.Text = "short";
this.rd_short.UseVisualStyleBackColor = true;
//
// txt_address
//
this.txt_address.Location = new System.Drawing.Point(56, 16);
this.txt_address.Name = "txt_address";
this.txt_address.Size = new System.Drawing.Size(121, 21);
this.txt_address.TabIndex = 9;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(9, 22);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(41, 12);
this.label3.TabIndex = 8;
this.label3.Text = "地址:";
//
// button3
//
this.button3.Location = new System.Drawing.Point(196, 14);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(75, 23);
this.button3.TabIndex = 7;
this.button3.Text = "读取";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// txt_value
//
this.txt_value.Location = new System.Drawing.Point(447, 16);
this.txt_value.Name = "txt_value";
this.txt_value.Size = new System.Drawing.Size(100, 21);
this.txt_value.TabIndex = 12;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(400, 22);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(29, 12);
this.label4.TabIndex = 11;
this.label4.Text = "值:";
//
// button4
//
this.button4.Location = new System.Drawing.Point(567, 15);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(75, 23);
this.button4.TabIndex = 10;
this.button4.Text = "写入";
this.button4.UseVisualStyleBackColor = true;
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// txt_content
//
this.txt_content.Location = new System.Drawing.Point(25, 166);
this.txt_content.Multiline = true;
this.txt_content.Name = "txt_content";
this.txt_content.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txt_content.Size = new System.Drawing.Size(656, 272);
this.txt_content.TabIndex = 13;
//
// txt_stationNumber
//
this.txt_stationNumber.Location = new System.Drawing.Point(457, 18);
this.txt_stationNumber.Name = "txt_stationNumber";
this.txt_stationNumber.Size = new System.Drawing.Size(35, 21);
this.txt_stationNumber.TabIndex = 14;
this.txt_stationNumber.Text = "1";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(410, 22);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(41, 12);
this.label5.TabIndex = 15;
this.label5.Text = "站号:";
//
// rd_bit
//
this.rd_bit.AutoSize = true;
this.rd_bit.Location = new System.Drawing.Point(11, 23);
this.rd_bit.Name = "rd_bit";
this.rd_bit.Size = new System.Drawing.Size(47, 16);
this.rd_bit.TabIndex = 16;
this.rd_bit.Text = "线圈";
this.rd_bit.UseVisualStyleBackColor = true;
//
// rd_ushort
//
this.rd_ushort.AutoSize = true;
this.rd_ushort.Location = new System.Drawing.Point(129, 23);
this.rd_ushort.Name = "rd_ushort";
this.rd_ushort.Size = new System.Drawing.Size(59, 16);
this.rd_ushort.TabIndex = 17;
this.rd_ushort.Text = "ushort";
this.rd_ushort.UseVisualStyleBackColor = true;
//
// rd_uint
//
this.rd_uint.AutoSize = true;
this.rd_uint.Location = new System.Drawing.Point(253, 23);
this.rd_uint.Name = "rd_uint";
this.rd_uint.Size = new System.Drawing.Size(47, 16);
this.rd_uint.TabIndex = 19;
this.rd_uint.Text = "uint";
this.rd_uint.UseVisualStyleBackColor = true;
//
// rd_int
//
this.rd_int.AutoSize = true;
this.rd_int.Location = new System.Drawing.Point(194, 23);
this.rd_int.Name = "rd_int";
this.rd_int.Size = new System.Drawing.Size(41, 16);
this.rd_int.TabIndex = 18;
this.rd_int.Text = "int";
this.rd_int.UseVisualStyleBackColor = true;
//
// rd_ulong
//
this.rd_ulong.AutoSize = true;
this.rd_ulong.Location = new System.Drawing.Point(374, 23);
this.rd_ulong.Name = "rd_ulong";
this.rd_ulong.Size = new System.Drawing.Size(53, 16);
this.rd_ulong.TabIndex = 21;
this.rd_ulong.Text = "ulong";
this.rd_ulong.UseVisualStyleBackColor = true;
//
// rd_long
//
this.rd_long.AutoSize = true;
this.rd_long.Location = new System.Drawing.Point(315, 23);
this.rd_long.Name = "rd_long";
this.rd_long.Size = new System.Drawing.Size(47, 16);
this.rd_long.TabIndex = 20;
this.rd_long.Text = "long";
this.rd_long.UseVisualStyleBackColor = true;
//
// rd_double
//
this.rd_double.AutoSize = true;
this.rd_double.Location = new System.Drawing.Point(495, 23);
this.rd_double.Name = "rd_double";
this.rd_double.Size = new System.Drawing.Size(59, 16);
this.rd_double.TabIndex = 23;
this.rd_double.Text = "double";
this.rd_double.UseVisualStyleBackColor = true;
//
// rd_float
//
this.rd_float.AutoSize = true;
this.rd_float.Location = new System.Drawing.Point(436, 23);
this.rd_float.Name = "rd_float";
this.rd_float.Size = new System.Drawing.Size(53, 16);
this.rd_float.TabIndex = 22;
this.rd_float.Text = "float";
this.rd_float.UseVisualStyleBackColor = true;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.rd_float);
this.groupBox1.Controls.Add(this.rd_double);
this.groupBox1.Controls.Add(this.rd_short);
this.groupBox1.Controls.Add(this.rd_bit);
this.groupBox1.Controls.Add(this.rd_ulong);
this.groupBox1.Controls.Add(this.rd_ushort);
this.groupBox1.Controls.Add(this.rd_long);
this.groupBox1.Controls.Add(this.rd_int);
this.groupBox1.Controls.Add(this.rd_uint);
this.groupBox1.Location = new System.Drawing.Point(25, 61);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(656, 53);
this.groupBox1.TabIndex = 24;
this.groupBox1.TabStop = false;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.button1);
this.groupBox2.Controls.Add(this.but_open);
this.groupBox2.Controls.Add(this.label5);
this.groupBox2.Controls.Add(this.txt_ip);
this.groupBox2.Controls.Add(this.txt_stationNumber);
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.txt_port);
this.groupBox2.Location = new System.Drawing.Point(25, 9);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(656, 54);
this.groupBox2.TabIndex = 25;
this.groupBox2.TabStop = false;
//
// groupBox3
//
this.groupBox3.Controls.Add(this.button3);
this.groupBox3.Controls.Add(this.label3);
this.groupBox3.Controls.Add(this.txt_address);
this.groupBox3.Controls.Add(this.button4);
this.groupBox3.Controls.Add(this.txt_value);
this.groupBox3.Controls.Add(this.label4);
this.groupBox3.Location = new System.Drawing.Point(25, 113);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(656, 47);
this.groupBox3.TabIndex = 26;
this.groupBox3.TabStop = false;
//
// ModBusTcpForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(707, 450);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.txt_content);
this.Name = "ModBusTcpForm";
this.Text = "ModBusTcp";
this.Load += new System.EventHandler(this.ModBusTcp_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button but_open;
private System.Windows.Forms.TextBox txt_ip;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txt_port;
private System.Windows.Forms.RadioButton rd_short;
private System.Windows.Forms.TextBox txt_address;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.TextBox txt_value;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.TextBox txt_content;
private System.Windows.Forms.TextBox txt_stationNumber;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.RadioButton rd_bit;
private System.Windows.Forms.RadioButton rd_ushort;
private System.Windows.Forms.RadioButton rd_uint;
private System.Windows.Forms.RadioButton rd_int;
private System.Windows.Forms.RadioButton rd_ulong;
private System.Windows.Forms.RadioButton rd_long;
private System.Windows.Forms.RadioButton rd_double;
private System.Windows.Forms.RadioButton rd_float;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.GroupBox groupBox3;
}
}

View File

@ -0,0 +1,194 @@
using IoTClient.Clients.ModBus;
using IoTServer.Servers.ModBus;
using System;
using System.Windows.Forms;
namespace IoTClient.Demo
{
public partial class ModBusTcpForm : Form
{
ModBusTcpClient client;
ModBusTcpServer server;
public ModBusTcpForm()
{
InitializeComponent();
button3.Enabled = false;
button4.Enabled = false;
toolTip1.SetToolTip(button1, "开启本地ModBusTcp服务端仿真模拟服务");
toolTip1.SetToolTip(but_open, "点击打开连接");
}
private void button1_Click(object sender, EventArgs e)
{
if (server == null)
{
server = new ModBusTcpServer("127.0.0.1", 502);
}
if (button1.Text == "本地模拟服务")
{
server.Start();
button1.Text = "模拟服务已启动";
}
else
{
server.Close();
button1.Text = "本地模拟服务";
}
}
private void button2_Click(object sender, EventArgs e)
{
if (but_open.Text == "连接")
{
client?.Close();
client = new ModBusTcpClient(txt_ip.Text?.Trim(), int.Parse(txt_port.Text?.Trim()));
if (client.Open())
{
but_open.Text = "已连接";
button3.Enabled = true;
button4.Enabled = true;
toolTip1.SetToolTip(but_open, "点击关闭连接");
}
else
{
MessageBox.Show("连接失败");
}
}
else
{
client?.Close();
but_open.Text = "连接";
toolTip1.SetToolTip(but_open, "点击打开连接");
}
}
private void button3_Click(object sender, EventArgs e)
{
byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
if (string.IsNullOrWhiteSpace(txt_address.Text))
{
MessageBox.Show("请输入地址");
return;
}
dynamic result = null;
if (rd_bit.Checked)
{
result = client.ReadCoil(txt_address.Text, stationNumber);
}
else if (rd_short.Checked)
{
result = client.ReadInt16(txt_address.Text, stationNumber);
}
else if (rd_ushort.Checked)
{
result = client.ReadUInt16(txt_address.Text, stationNumber);
}
else if (rd_int.Checked)
{
result = client.ReadInt32(txt_address.Text, stationNumber);
}
else if (rd_uint.Checked)
{
result = client.ReadUInt32(txt_address.Text, stationNumber);
}
else if (rd_long.Checked)
{
result = client.ReadInt64(txt_address.Text, stationNumber);
}
else if (rd_ulong.Checked)
{
result = client.ReadUInt64(txt_address.Text, stationNumber);
}
else if (rd_float.Checked)
{
result = client.ReadFloat(txt_address.Text, stationNumber);
}
else if (rd_double.Checked)
{
result = client.ReadDouble(txt_address.Text, stationNumber);
}
if (result.IsSucceed)
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][读取 {txt_address.Text?.Trim()} 成功]{result.Value}\r\n");
else
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][读取 {txt_address.Text?.Trim()} 失败]{result.Err}\r\n");
}
private void button4_Click(object sender, EventArgs e)
{
byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
if (string.IsNullOrWhiteSpace(txt_address.Text))
{
MessageBox.Show("请输入地址");
return;
}
if (string.IsNullOrWhiteSpace(txt_value.Text))
{
MessageBox.Show("请输入值");
return;
}
dynamic result = null;
if (rd_bit.Checked)
{
if (!bool.TryParse(txt_value.Text?.Trim(), out bool coil))
{
if (txt_value.Text?.Trim() == "0")
coil = false;
else if (txt_value.Text?.Trim() == "1")
coil = true;
else
{
MessageBox.Show("请输入 True 或 False");
return;
}
}
result = client.Write(txt_address.Text, coil, stationNumber);
}
else if (rd_short.Checked)
{
result = client.Write(txt_address.Text, short.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_ushort.Checked)
{
result = client.Write(txt_address.Text, ushort.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_int.Checked)
{
result = client.Write(txt_address.Text, int.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_uint.Checked)
{
result = client.Write(txt_address.Text, uint.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_long.Checked)
{
result = client.Write(txt_address.Text, long.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_ulong.Checked)
{
result = client.Write(txt_address.Text, ulong.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_float.Checked)
{
result = client.Write(txt_address.Text, float.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_double.Checked)
{
result = client.Write(txt_address.Text, double.Parse(txt_value.Text?.Trim()), stationNumber);
}
if (result.IsSucceed)
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 成功]OK\r\n");
else
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 失败]{result.Err}\r\n");
}
private void ModBusTcp_Load(object sender, EventArgs e)
{
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -16,7 +16,7 @@ namespace IoTClient.Demo
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ModBusTcp());
Application.Run(new ModBusTcpForm());
}
}
}

View File

@ -25,23 +25,23 @@ namespace IoTClient.Tests.ModBus
public async Task ()
{
short Number = 33;
client.Write(4, Number, stationNumber);
client.Write("4", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
Number = 34;
client.Write(4, Number, stationNumber);
client.Write("4", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
Number = 1;
client.Write(12, Number, stationNumber);
client.Write("12", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(12, stationNumber).Value == 1);
Assert.True(client.ReadInt16("12", stationNumber).Value == 1);
Number = 0;
client.Write(12, Number, stationNumber);
client.Write("12", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(12, stationNumber).Value == 0);
Assert.True(client.ReadInt16("12", stationNumber).Value == 0);
}
[Fact]
@ -50,23 +50,23 @@ namespace IoTClient.Tests.ModBus
client.Open();
short Number = 33;
client.Write(4, Number, stationNumber);
client.Write("4", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
Number = 34;
client.Write(4, Number, stationNumber);
client.Write("4", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
Number = 1;
client.Write(12, Number, stationNumber);
client.Write("12", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(12, stationNumber).Value == 1);
Assert.True(client.ReadInt16("12", stationNumber).Value == 1);
Number = 0;
client.Write(12, Number, stationNumber);
client.Write("12", Number, stationNumber);
await Task.Delay(500);
Assert.True(client.ReadInt16(12, stationNumber).Value == 0);
Assert.True(client.ReadInt16("12", stationNumber).Value == 0);
client.Close();
}

View File

@ -28,6 +28,7 @@ namespace IoTClient.Clients.ModBus
/// <returns></returns>
protected override bool Connect()
{
socket?.Close();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
@ -65,7 +66,7 @@ namespace IoTClient.Clients.ModBus
/// <param name="functionCode">功能码</param>
/// <param name="readLength">读取长度</param>
/// <returns></returns>
public Result<byte[]> Read(ushort address, byte stationNumber = 1, byte functionCode = 3, ushort readLength = 1)
public Result<byte[]> Read(string address, byte stationNumber = 1, byte functionCode = 3, ushort readLength = 1)
{
ConnectManager();
var readResult = new Result<byte[]>();
@ -113,7 +114,7 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<short> ReadInt16(ushort address, byte stationNumber = 1, byte functionCode = 3)
public Result<short> ReadInt16(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode);
var result = new Result<short>()
@ -127,6 +128,27 @@ namespace IoTClient.Clients.ModBus
return result;
}
/// <summary>
/// 读取UInt16
/// </summary>
/// <param name="address">寄存器起始地址</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<ushort> ReadUInt16(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode);
var result = new Result<ushort>()
{
IsSucceed = readResut.IsSucceed,
Err = readResut.Err,
ErrList = readResut.ErrList,
};
if (result.IsSucceed)
result.Value = BitConverter.ToUInt16(readResut.Value, 0);
return result;
}
/// <summary>
/// 读取Int32
/// </summary>
@ -134,7 +156,7 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<int> ReadInt32(ushort address, byte stationNumber = 1, byte functionCode = 3)
public Result<int> ReadInt32(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
var result = new Result<int>()
@ -148,6 +170,27 @@ namespace IoTClient.Clients.ModBus
return result;
}
/// <summary>
/// 读取UInt32
/// </summary>
/// <param name="address">寄存器起始地址</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<uint> ReadUInt32(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
var result = new Result<uint>()
{
IsSucceed = readResut.IsSucceed,
Err = readResut.Err,
ErrList = readResut.ErrList,
};
if (result.IsSucceed)
result.Value = BitConverter.ToUInt32(readResut.Value, 0);
return result;
}
/// <summary>
/// 读取Int64
/// </summary>
@ -155,9 +198,9 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<long> ReadInt64(ushort address, byte stationNumber = 1, byte functionCode = 3)
public Result<long> ReadInt64(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
var readResut = Read(address, stationNumber, functionCode, readLength: 4);
var result = new Result<long>()
{
IsSucceed = readResut.IsSucceed,
@ -169,6 +212,27 @@ namespace IoTClient.Clients.ModBus
return result;
}
/// <summary>
/// 读取UInt64
/// </summary>
/// <param name="address">寄存器起始地址</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<ulong> ReadUInt64(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode, readLength: 4);
var result = new Result<ulong>()
{
IsSucceed = readResut.IsSucceed,
Err = readResut.Err,
ErrList = readResut.ErrList,
};
if (result.IsSucceed)
result.Value = BitConverter.ToUInt64(readResut.Value, 0);
return result;
}
/// <summary>
/// 读取Float
/// </summary>
@ -176,7 +240,7 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<float> ReadFloat(ushort address, byte stationNumber = 1, byte functionCode = 3)
public Result<float> ReadFloat(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
var result = new Result<float>()
@ -197,9 +261,9 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<double> ReadDouble(ushort address, byte stationNumber = 1, byte functionCode = 3)
public Result<double> ReadDouble(string address, byte stationNumber = 1, byte functionCode = 3)
{
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
var readResut = Read(address, stationNumber, functionCode, readLength: 4);
var result = new Result<double>()
{
IsSucceed = readResut.IsSucceed,
@ -218,7 +282,7 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public Result<bool> ReadCoil(ushort address, byte stationNumber = 1, byte functionCode = 1)
public Result<bool> ReadCoil(string address, byte stationNumber = 1, byte functionCode = 1)
{
var readResut = Read(address, stationNumber, functionCode);
var result = new Result<bool>()
@ -234,6 +298,7 @@ namespace IoTClient.Clients.ModBus
#endregion
#region Write
/// <summary>
/// 线圈写入
/// </summary>
@ -241,7 +306,7 @@ namespace IoTClient.Clients.ModBus
/// <param name="value"></param>
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
public Result Write(ushort address, bool value, byte stationNumber = 1, byte functionCode = 5)
public Result Write(string address, bool value, byte stationNumber = 1, byte functionCode = 5)
{
ConnectManager();
var result = new Result();
@ -249,6 +314,11 @@ namespace IoTClient.Clients.ModBus
{
var command = GetWriteCoilCommand(address, value, stationNumber, functionCode);
socket.Send(command);
//获取响应报文
var headBytes = SocketRead(socket, 8);
int length = headBytes[4] * 256 + headBytes[5] - 2;
SocketRead(socket, length);
}
catch (SocketException ex)
{
@ -274,17 +344,17 @@ namespace IoTClient.Clients.ModBus
/// <summary>
/// 写入
/// </summary>
/// <param name="address">寄存器地址</param>
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(ushort address, short value, byte stationNumber = 1, byte functionCode = 16)
/// <param name="address"></param>
/// <param name="values"></param>
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
/// <returns></returns>
public Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16)
{
ConnectManager();
var result = new Result();
try
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
var command = GetWriteCommand(address, values, stationNumber, functionCode);
socket.Send(command);
@ -321,40 +391,10 @@ namespace IoTClient.Clients.ModBus
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(ushort address, int value, byte stationNumber = 1, byte functionCode = 16)
public Result Write(string address, short value, byte stationNumber = 1, byte functionCode = 16)
{
ConnectManager();
var result = new Result();
try
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
var command = GetWriteCommand(address, values, stationNumber, functionCode);
socket.Send(command);
//获取响应报文
var headBytes = SocketRead(socket, 8);
int length = headBytes[4] * 256 + headBytes[5] - 2;
SocketRead(socket, length);
}
catch (SocketException ex)
{
result.IsSucceed = false;
if (ex.SocketErrorCode == SocketError.TimedOut)
{
result.Err = "连接超时";
result.ErrList.Add("连接超时");
}
else
{
result.Err = ex.Message;
result.ErrList.Add(ex.Message);
}
}
finally
{
if (isAutoOpen.Value) Dispose();
}
return result;
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
/// <summary>
@ -364,40 +404,10 @@ namespace IoTClient.Clients.ModBus
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(ushort address, long value, byte stationNumber = 1, byte functionCode = 16)
public Result Write(string address, ushort value, byte stationNumber = 1, byte functionCode = 16)
{
ConnectManager();
var result = new Result();
try
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
var command = GetWriteCommand(address, values, stationNumber, functionCode);
socket.Send(command);
//获取响应报文
var headBytes = SocketRead(socket, 8);
int length = headBytes[4] * 256 + headBytes[5] - 2;
SocketRead(socket, length);
}
catch (SocketException ex)
{
result.IsSucceed = false;
if (ex.SocketErrorCode == SocketError.TimedOut)
{
result.Err = "连接超时";
result.ErrList.Add("连接超时");
}
else
{
result.Err = ex.Message;
result.ErrList.Add(ex.Message);
}
}
finally
{
if (isAutoOpen.Value) Dispose();
}
return result;
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
/// <summary>
@ -407,40 +417,10 @@ namespace IoTClient.Clients.ModBus
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(ushort address, float value, byte stationNumber = 1, byte functionCode = 16)
public Result Write(string address, int value, byte stationNumber = 1, byte functionCode = 16)
{
ConnectManager();
var result = new Result();
try
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
var command = GetWriteCommand(address, values, stationNumber, functionCode);
socket.Send(command);
//获取响应报文
var headBytes = SocketRead(socket, 8);
int length = headBytes[4] * 256 + headBytes[5] - 2;
SocketRead(socket, length);
}
catch (SocketException ex)
{
result.IsSucceed = false;
if (ex.SocketErrorCode == SocketError.TimedOut)
{
result.Err = "连接超时";
result.ErrList.Add("连接超时");
}
else
{
result.Err = ex.Message;
result.ErrList.Add(ex.Message);
}
}
finally
{
if (isAutoOpen.Value) Dispose();
}
return result;
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
/// <summary>
@ -450,40 +430,62 @@ namespace IoTClient.Clients.ModBus
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(ushort address, double value, byte stationNumber = 1, byte functionCode = 16)
public Result Write(string address, uint value, byte stationNumber = 1, byte functionCode = 16)
{
ConnectManager();
var result = new Result();
try
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
var command = GetWriteCommand(address, values, stationNumber, functionCode);
socket.Send(command);
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
//获取响应报文
var headBytes = SocketRead(socket, 8);
int length = headBytes[4] * 256 + headBytes[5] - 2;
SocketRead(socket, length);
}
catch (SocketException ex)
{
result.IsSucceed = false;
if (ex.SocketErrorCode == SocketError.TimedOut)
{
result.Err = "连接超时";
result.ErrList.Add("连接超时");
}
else
{
result.Err = ex.Message;
result.ErrList.Add(ex.Message);
}
}
finally
{
if (isAutoOpen.Value) Dispose();
}
return result;
/// <summary>
/// 写入
/// </summary>
/// <param name="address">寄存器地址</param>
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(string address, long value, byte stationNumber = 1, byte functionCode = 16)
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
/// <summary>
/// 写入
/// </summary>
/// <param name="address">寄存器地址</param>
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(string address, ulong value, byte stationNumber = 1, byte functionCode = 16)
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
/// <summary>
/// 写入
/// </summary>
/// <param name="address">寄存器地址</param>
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(string address, float value, byte stationNumber = 1, byte functionCode = 16)
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
/// <summary>
/// 写入
/// </summary>
/// <param name="address">寄存器地址</param>
/// <param name="value">写入的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(string address, double value, byte stationNumber = 1, byte functionCode = 16)
{
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
#endregion
@ -497,8 +499,9 @@ namespace IoTClient.Clients.ModBus
/// <param name="functionCode">功能码</param>
/// <param name="length">读取长度</param>
/// <returns></returns>
public byte[] GetReadCommand(ushort address, byte stationNumber, byte functionCode, ushort length)
public byte[] GetReadCommand(string address, byte stationNumber, byte functionCode, ushort length)
{
var readAddress = ushort.Parse(address?.Trim());
byte[] buffer = new byte[12];
buffer[0] = 0x19;
buffer[1] = 0xB2;//Client发出的检验信息
@ -509,8 +512,8 @@ namespace IoTClient.Clients.ModBus
buffer[6] = stationNumber; //站号
buffer[7] = functionCode; //功能码
buffer[8] = BitConverter.GetBytes(address)[1];
buffer[9] = BitConverter.GetBytes(address)[0];//寄存器地址
buffer[8] = BitConverter.GetBytes(readAddress)[1];
buffer[9] = BitConverter.GetBytes(readAddress)[0];//寄存器地址
buffer[10] = BitConverter.GetBytes(length)[1];
buffer[11] = BitConverter.GetBytes(length)[0];//表示request 寄存器的长度(寄存器个数)
return buffer;
@ -524,8 +527,9 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public byte[] GetWriteCommand(ushort address, byte[] values, byte stationNumber, byte functionCode)
public byte[] GetWriteCommand(string address, byte[] values, byte stationNumber, byte functionCode)
{
var writeAddress = ushort.Parse(address?.Trim());
byte[] buffer = new byte[13 + values.Length];
buffer[0] = 0x19;
buffer[1] = 0xB2;//检验信息用来验证response是否串数据了
@ -534,8 +538,8 @@ namespace IoTClient.Clients.ModBus
buffer[6] = stationNumber; //站号
buffer[7] = functionCode; //功能码
buffer[8] = BitConverter.GetBytes(address)[1];
buffer[9] = BitConverter.GetBytes(address)[0];//寄存器地址
buffer[8] = BitConverter.GetBytes(writeAddress)[1];
buffer[9] = BitConverter.GetBytes(writeAddress)[0];//寄存器地址
buffer[10] = (byte)(values.Length / 2 / 256);
buffer[11] = (byte)(values.Length / 2 % 256);//写寄存器数量(除2是两个字节一个寄存器寄存器16位。除以256是byte最大存储255。)
buffer[12] = (byte)(values.Length); //写字节的个数
@ -551,8 +555,9 @@ namespace IoTClient.Clients.ModBus
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <returns></returns>
public byte[] GetWriteCoilCommand(ushort address, bool value, byte stationNumber, byte functionCode)
public byte[] GetWriteCoilCommand(string address, bool value, byte stationNumber, byte functionCode)
{
var writeAddress = ushort.Parse(address?.Trim());
byte[] buffer = new byte[12];
buffer[0] = 0x19;
buffer[1] = 0xB2;//Client发出的检验信息
@ -561,8 +566,8 @@ namespace IoTClient.Clients.ModBus
buffer[6] = stationNumber;//站号
buffer[7] = functionCode; //功能码
buffer[8] = BitConverter.GetBytes(address)[1];
buffer[9] = BitConverter.GetBytes(address)[0];//寄存器地址
buffer[8] = BitConverter.GetBytes(writeAddress)[1];
buffer[9] = BitConverter.GetBytes(writeAddress)[0];//寄存器地址
buffer[10] = (byte)(value ? 0xFF : 0x00); //此处只可以是FF表示闭合00表示断开其他数值非法
buffer[11] = 0x00;
return buffer;

View File

@ -50,7 +50,7 @@ namespace IoTClient.Core
{
try
{
socket?.Shutdown(SocketShutdown.Both);//正常关闭连接
if (socket.Connected) socket?.Shutdown(SocketShutdown.Both);//正常关闭连接
socket?.Close();
return true;
}

View File

@ -11,16 +11,13 @@ namespace IoTServer.Servers.ModBus
{
private Socket socketServer;
private string redisConfig;
private string ip;
private int port;
public ModBusTcpServer(string ip, int port, string redisConfig = null)
{
this.redisConfig = redisConfig;
//1 创建Socket对象
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2 绑定ip和端口
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
socketServer.Bind(ipEndPoint);
this.ip = ip;
this.port = port;
}
/// <summary>
@ -28,12 +25,26 @@ namespace IoTServer.Servers.ModBus
/// </summary>
public void Start()
{
//1 创建Socket对象
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2 绑定ip和端口
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
socketServer.Bind(ipEndPoint);
//3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10
socketServer.Listen(10);
Task.Run(() => { Accept(socketServer); });
}
public void Close()
{
if (socketServer?.Connected ?? false)
socketServer.Shutdown(SocketShutdown.Both);
socketServer?.Close();
}
/// <summary>
/// 客户端连接到服务端
/// </summary>
@ -42,9 +53,18 @@ namespace IoTServer.Servers.ModBus
{
while (true)
{
//阻塞等待客户端连接
Socket newSocket = socket.Accept();
Task.Run(() => { Receive(newSocket); });
try
{
//阻塞等待客户端连接
Socket newSocket = socket.Accept();
Task.Run(() => { Receive(newSocket); });
}
catch (SocketException ex)
{
if (ex.SocketErrorCode != SocketError.Interrupted)
throw ex;
}
}
}
@ -84,6 +104,14 @@ namespace IoTServer.Servers.ModBus
switch (requetData[7])
{
//读取线圈
case 1:
//TODO
break;
//写入线圈
case 5:
//TODO
break;
//读取
case 3:
{
@ -102,7 +130,8 @@ namespace IoTServer.Servers.ModBus
case 16:
{
//TODO
data.Write(requetData[9], requetData[requetData.Length - 1].ToString());
var value = requetData[requetData.Length - 2] * 256 + requetData[requetData.Length - 1];
data.Write(requetData[9], value.ToString());
var responseData = new byte[12];
Buffer.BlockCopy(requetData, 0, responseData, 0, responseData.Length);
responseData[5] = 6;
@ -111,10 +140,11 @@ namespace IoTServer.Servers.ModBus
break;
}
}
catch (Exception ex)
catch (SocketException ex)
{
//todo
throw ex;
if (ex.SocketErrorCode != SocketError.ConnectionRefused)
throw ex;
}
}
}