C#代码中SQLite数据库创建和表格初#region ModbusTCP客户端
/// <summary>
/// ModbusTCP客户端
/// </summary>
public class ModbusTCP
{
#region 对象
/*定义连接的Socket*/
Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //---通讯的socket
/*定义socket线程*/
Thread receiveTh; //-----------------------接收socket线程
#endregion
#region 事件
public del LogInfoDisplay; //----------------------委托变量-信息显示
public Action<string> returnReceiveEvent; //------接收返回数据事件
#endregion
#region 变量
/*运行中的状态*/
string nameClient; //---客户端名称
public InfoMsg info = new InfoMsg("", ""); //-----------------------显示信息
/*BIN指令*/
byte[] buffer = new byte[255];
/*接收到的数据*/
byte[] data; //--------数据
/*时间*/
DateTime startTime, stopTime;
DateTime stopTime1, stopTime2, stopTime3;
#endregion
#region 命令枚举
/// <summary>
/// 命令枚举
/// </summary>
enum Comand : short
{
读线圈寄存器 = 1, //-------单个或多个(M寄存器)
读输入状态 = 2, //---------单个或多个
读保存寄存器 = 3, //-------单个或多个(D寄存器)
读输入寄存器 = 4, //-------单个或多个
写单个线圈寄存器 = 5, //---(M寄存器)
写单个保存寄存器 = 6, //---(D寄存器)
写多个线圈寄存器 = 15, //--(M寄存器)
写多个保持寄存器 = 16, //--(D寄存器)
}
#endregion
#region 客户端初始化
/// <summary>
/// 客户端初始化
/// </summary>
/// <param name="name">客户端名称</param>
/// <param name="receiveData">接收数据事件</param>
/// <param name="info">消息显示事件</param>
public void Initial(string name = "客户端", Action<string> receiveData = null, del info = null)
{
nameClient = name; //-------------------客户端名称
returnReceiveEvent += receiveData; //---接收数据事件
LogInfoDisplay += info; //--------------消息事件
this.info.msgType = nameClient; //---log消息类型
}
#endregion
#region 断开连接
/*关闭客户端*/
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
if (ClientSocket != null)
{
if (ClientSocket.Connected == true)
{
ClientSocket.Close();
ClientSocket.Dispose();
info.msg = "Socket连接关闭成功";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
else
{
info.msg = "Socket连接不存在!";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
}
}
catch { }
try
{
if (receiveTh != null)
{
if (receiveTh.IsAlive == true)
{
ClientSocket.Close();
receiveTh.Abort(); //-----------------------接收socket线程关闭
receiveTh.DisableComObjectEagerCleanup();
info.msg = "客户端关闭成功!";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
else
{
info.msg = "客户端不存在!";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
}
}
catch { }
Thread.Sleep(100);
}
#endregion
#region 连接的Socket
/*连接的Socket*/
/// <summary>
/// 连接的Socket
/// </summary>
/// <param name="IP">IP地址</param>
/// <param name="Port">端口号</param>
public void Connection(string IP, string Port)
{
try
{
IPAddress ip = IPAddress.Parse(IP.Trim());
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(Port.Trim()));
if (ClientSocket != null)
{
ClientSocket.Dispose();
}
Disconnect();
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ClientSocket.Connect(point);
info.msgType = nameClient;
info.msg = "连接成功";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
/*开启一个新线程负责不停的接收服务器发过来的数据*/
if (receiveTh == null)
{
receiveTh = new Thread(Receive); //-----------------------接收socket线程
receiveTh.IsBackground = true;
receiveTh.Start();
}
else
{
if (receiveTh.IsAlive != true)
{
receiveTh = new Thread(Receive); //-----------------------接收socket线程
receiveTh.IsBackground = true;
receiveTh.Start();
}
}
}
catch { }
}
#endregion
#region 地址解析
/// <summary>
/// 地址解析
/// </summary>
/// <param name="addr">地址</param>
/// <returns>地址数组</returns>
private byte[] AddrResolver(string addr)
{
/*ModubusTCP读取命令固定格式
addrBuffer[0]-----地址H
addrBuffer[1]-----地址L
*/
char[] addrChar = addr.ToArray();
string addrStr = "";
byte[] addrBuffer = new byte[5];
for (int i = 1; i < addrChar.Length; i++)
{
addrStr += addrChar[i];
}
int addrInt = int.Parse(addrStr);
string addrStr2 = addrInt.ToString("x");
string addrStr3 = "";
switch (addrStr2.Length)
{
case 1:
addrStr3 = "0" + "0" + "0" + addrStr2;
break;
case 2:
addrStr3 = "0" + "0" + addrStr2;
break;
case 3:
addrStr3 = "0" + addrStr2;
break;
case 4:
addrStr3 = addrStr2;
break;
}
char[] addrChar2 = addrStr3.ToArray();
addrBuffer[0] = byte.Parse(addrChar2[0].ToString() + addrChar2[1].ToString(), System.Globalization.NumberStyles.HexNumber);
addrBuffer[1] = byte.Parse(addrChar2[2].ToString() + addrChar2[3].ToString(), System.Globalization.NumberStyles.HexNumber);
return addrBuffer;
}
#endregion
#region 读取线圈寄存器(M寄存器)
/// <summary>
/// 读取线圈寄存器
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="length">长度</param>
/// <returns>值</returns>
public bool[] ReadCoils(short ID, string addr, int length)
{
#region 读取线圈寄存器指令
/*BIN指令*/
/*读取线圈寄存器指令*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----线圈寄存器起始地址H
//buffer[9] = 0x01; //----线圈寄存器起始地址L
//buffer[10] = 0x00; //---线圈寄存器个数H
//buffer[11] = 0x01; //---线圈寄存器个数L
#endregion
#region 读取线圈寄存器指令反馈
/*读取线圈寄存器指令反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----线圈寄存器字节数:后面的数据字节数(例:线圈字节数=3时,数据有3个字节)
//buffer[9] = 0x01; //----数据
#endregion
bool[] result = new bool[length]; //--------------------读取线圈寄存器返回值
byte[] addrByte = AddrResolver(addr); //----------------线圈寄存器首地址数组
byte[] lenghtBuffer = WriteDataResolver(length); //-----线圈寄存器个数数组
#region 发送指令
/*BIN指令*/
/*读线圈寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = 0x06; //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.读线圈寄存器); //----功能码
buffer[8] = addrByte[0]; //--------起始线圈寄存器地址H
buffer[9] = addrByte[1]; //--------起始线圈寄存器地址L
buffer[10] = lenghtBuffer[0]; //---线圈寄存器个数H
buffer[11] = lenghtBuffer[1]; //---线圈寄存器个数L
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
Thread.Sleep(100);
#region 返回数据解析
int j = 1;
int m = 1;
try
{
for (int i = 0; i < length; i++)
{
if (i % 8 == 0)
{
j = 1;
m = 1;
}
if (i % 8 == 0)
{
m = 1 * j;
j = j * 10;
}
else
{
m = 2 * m;
}
result[i] = (data[i / 8] & m) == m ? true : false;
}
}
catch { }
#endregion
return result;
}
#endregion
#region 读取输入状态
/// <summary>
/// 读取输入状态
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="length">长度</param>
/// <returns>值</returns>
public bool[] ReadInput(short ID, string addr, int length)
{
#region 读取输入状态指令
/*BIN指令*/
/*读取输入状态指令*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----输入状态起始地址H
//buffer[9] = 0x01; //----输入状态起始地址L
//buffer[10] = 0x00; //---读取个数H
//buffer[11] = 0x01; //---读取个数L
#endregion
#region 读取输入状态指令反馈
/*读取输入状态指令反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----字节数:后面的数据字节数(例:线圈字节数=3时,数据有3个字节)
//buffer[9] = 0x01; //----输入状态
#endregion
byte count = length % 8 == 0 ? (byte)(length / 8) : (byte)(length / 8 + 1); //----字节长度
bool[] result = new bool[length]; //---------------------读取输入状态返回值
byte[] addrByte = AddrResolver(addr); //----------------输入状态起始地址数组
byte[] lenghtBuffer = WriteDataResolver(length); //-----输入状态个数数组
#region 发送指令
/*BIN指令*/
/*读输入寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = 0x06; //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.读输入状态); //----功能码
buffer[8] = addrByte[0]; //----输入状态起始地址H
buffer[9] = addrByte[1]; //----输入状态起始地址L
buffer[10] = lenghtBuffer[0]; //---读取个数H
buffer[11] = lenghtBuffer[1]; //---读取个数L
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
Thread.Sleep(100);
#region 返回数据解析
int j = 1;
int m = 1;
try
{
for (int i = 0; i < length; i++)
{
if (i % 8 == 0)
{
j = 1;
m = 1;
}
if (i % 8 == 0)
{
m = 1 * j;
j = j * 10;
}
else
{
m = 2 * m;
}
result[i] = (data[i / 8] & m) == m ? true : false;
}
}
catch { }
#endregion
return result;
}
#endregion
#region 读取保持寄存器(D寄存器)
/// <summary>
/// 读取类型
/// </summary>
public enum ReadTypeEnum : short
{
字 = 1,
双字 = 2
}
/// <summary>
/// 读取保持寄存器
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="length">长度</param>
/// <param name="type">类型</param>
/// <returns>值</returns>
public long[] ReadHoldingRegister(short ID, string addr, int length, ReadTypeEnum type = ReadTypeEnum.字)
{
#region 读保持寄存器反馈指令
/*BIN指令*/
/*读保持寄存器指令*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----寄存器起始地址H
//buffer[9] = 0x01; //----寄存器起始地址L
//buffer[10] = 0x00; //---寄存器个数H
//buffer[11] = 0x01; //---寄存器个数L
#endregion
#region 读保持寄存器反馈指令反馈
/*读保持寄存器反馈指令反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----寄存器个数
//buffer[9] = 0x01; //----寄存器数据H_每个数2个字节
//buffer[10] = 0x01; //---寄存器数据L_每个数2个字节
#endregion
startTime = DateTime.Now;
long[] result = new long[length]; //----------------------读取寄存器返回值
byte[] addrByte = AddrResolver(addr); //------------------------------寄存器首地址数组
byte[] lenghtBuffer = WriteDataResolver(length * (short)type); //-----寄存器个数数组
#region 发送指令
/*BIN指令*/
/*读保持寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = 0x06; //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.读保存寄存器); //----功能码
buffer[8] = addrByte[0]; //----起始寄存器地址H
buffer[9] = addrByte[1]; //----起始寄存器地址L
buffer[10] = lenghtBuffer[0]; //---寄存器个数H
buffer[11] = lenghtBuffer[1]; //---寄存器个数L
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
stopTime1 = DateTime.Now;
info.msg = "发送时间(毫秒):" + stopTime1.Subtract(startTime).Milliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
Thread.Sleep(5);
#region 返回数据解析
try
{
if (type == ReadTypeEnum.字)
{
for (int i = 0; i < 2 * length; i = i + 2)
{
result[i / 2] = data[i] * 256 + data[i + 1];
//负数求补码
if (result[i] > 0x8000)
{
result[i] = GetComplementer(result[i], 2);
result[i] = -result[i];
}
}
}
if (type == ReadTypeEnum.双字)
{
for (int i = 0; i < 4 * length; i = i + 4)
{
result[i / 4] = data[i] * 256 + data[i + 1] + data[i + 2] * 256 * 256 * 256 + data[i + 3] * 256 * 256;
//负数求补码
if (result[i] > 0x80000000)
{
result[i] = GetComplementer(result[i], 4);
result[i] = -result[i];
}
}
}
}
catch { }
#endregion
stopTime = DateTime.Now;
info.msg = "读取总时间(毫秒):" + stopTime.Subtract(startTime).Milliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
return result;
}
#endregion
#region 读取输入寄存器
/// <summary>
/// 读取输入寄存器
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="length">长度</param>
/// <param name="type">类型</param>
/// <returns>值</returns>
public long[] ReadInputRegister(short ID, string addr, int length, ReadTypeEnum type = ReadTypeEnum.字)
{
#region 读取输入寄存器指令
/*BIN指令*/
/*读取输入寄存器指令*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----输入寄存器起始地址H
//buffer[9] = 0x01; //----输入寄存器起始地址L
//buffer[10] = 0x00; //---读取个数H
//buffer[11] = 0x01; //---读取个数L
#endregion
#region 读取输入寄存器指令反馈
/*读取输入寄存器指令反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----字节数:后面的数据字节数(例:线圈字节数=3时,数据有3个字节)
//buffer[9] = 0x01; //----输入状态
#endregion
long[] result = new long[length]; //--------------------读取输入寄存器返回值
byte[] addrByte = AddrResolver(addr); //----------------输入寄存器起始地址数组
byte[] lenghtBuffer = WriteDataResolver(length * (short)type); //-----输入寄存器个数数组
#region 发送指令
/*BIN指令*/
/*读输入寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = 0x06; //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.读输入寄存器); //----功能码
buffer[8] = addrByte[0]; //----输入寄存器起始地址H
buffer[9] = addrByte[1]; //----输入寄存器起始地址L
buffer[10] = lenghtBuffer[0]; //---读取个数H
buffer[11] = lenghtBuffer[1]; //---读取个数L
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
Thread.Sleep(100);
#region 返回数据解析
try
{
if (type == ReadTypeEnum.字)
{
for (int i = 0; i < 2 * length; i = i + 2)
{
result[i / 2] = data[i] * 256 + data[i + 1];
//负数求补码
if (result[i] > 0x8000)
{
result[i] = GetComplementer(result[i], 2);
result[i] = -result[i];
}
}
}
if (type == ReadTypeEnum.双字)
{
for (int i = 0; i < 4 * length; i = i + 4)
{
result[i / 4] = data[i] * 256 + data[i + 1] + data[i + 2] * 256 * 256 * 256 + data[i + 3] * 256 * 256;
//负数求补码
if (result[i] > 0x80000000)
{
result[i] = GetComplementer(result[i], 4);
result[i] = -result[i];
}
}
}
}
catch { }
#endregion
return result;
}
#endregion
#region 写入单个线圈寄存器值(M寄存器)
/// <summary>
/// 写入单个线圈寄存器值
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="value">值</param>
public void WriteSingleCoils(short ID, string addr, string value)
{
#region 写入单个线圈寄存器值
/*BIN指令*/
/*写入单个线圈寄存器值*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----线圈寄存器地址H
//buffer[9] = 0x01; //----线圈寄存器地址L
//buffer[10] = 0x00; //---设置值H
//buffer[11] = 0x01; //---设置值L
#endregion
#region 写入单个线圈寄存器反馈
/*写入单个线圈寄存器反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----线圈寄存器地址H
//buffer[9] = 0x01; //----线圈寄存器地址L
//buffer[10] = 0x00; //---设置值H
//buffer[11] = 0x01; //---设置值L
#endregion
byte[] addrByte = AddrResolver(addr); //-----------线圈寄存器起始地址数组
byte[] data = new byte[2]; //----------------------写入数据
#region 写入数据
if (value == "0" || value == "false")
{
data[0] = 0x00;
data[1] = 0x00;
}
if (value != "0" || value == "true")
{
data[0] = 0xff;
data[1] = 0x00;
}
#endregion
#region 发送指令
/*BIN指令*/
/*写单个线圈寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = 0x06; //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.写单个线圈寄存器); //----功能码
buffer[8] = addrByte[0]; //----起始线圈寄存器地址H
buffer[9] = addrByte[1]; //----起始线圈寄存器地址L
buffer[10] = data[0]; //---设定值H
buffer[11] = data[1]; //---设定值L
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
}
#endregion
#region 写入单个保持寄存器值(D寄存器)
/// <summary>
/// 写入单个保持寄存器值
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="value">值</param>
public void WriteSingleRegister(short ID, string addr, string value)
{
#region 写入单个保持寄存器值
/*BIN指令*/
/*写入单个保持寄存器值*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----寄存器地址H
//buffer[9] = 0x01; //----寄存器地址L
//buffer[10] = 0x00; //---设置值H
//buffer[11] = 0x01; //---设置值L
#endregion
#region 写入单个保持寄存器反馈
/*写入单个保持寄存器反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----寄存器地址H
//buffer[9] = 0x01; //----寄存器地址L
//buffer[10] = 0x00; //---设置值H
//buffer[11] = 0x01; //---设置值L
#endregion
byte[] addrByte = AddrResolver(addr); //-----------线圈地址数组
byte[] data = WriteDataResolver(value, 2); //---------写入数据
#region 发送指令
/*BIN指令*/
/*写单个保持寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = 0x06; //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.写单个保存寄存器); //----功能码
buffer[8] = addrByte[0]; //----起始线圈地址H
buffer[9] = addrByte[1]; //----起始线圈地址L
buffer[10] = data[0]; //---设置值H
buffer[11] = data[1]; //---设置值L
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
}
#endregion
#region 写入多个线圈寄存器值(M寄存器)
/// <summary>
/// 写入多个线圈寄存器值
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="length">长度</param>
/// <param name="value">值</param>
public void WriteMultipleleCoils(short ID, string addr, int length, int value)
{
#region 写入多个线圈值
/*BIN指令*/
/*写入多个线圈寄存器值*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----线圈寄存器起始地址H
//buffer[9] = 0x01; //----线圈寄存器起始地址L
//buffer[10] = 0x00; //---设置长度H
//buffer[11] = 0x01; //---设置长度L
//buffer[12] = 0x00; //---字节长度
//buffer[13] = 0x01; //---设置值1H
//buffer[14] = 0x00; //---设置值1L
//buffer[15] = 0x01; //---设置值2H
//buffer[16] = 0x00; //---设置值2L
#endregion
#region 写入多个线圈寄存器反馈
/*写入多个线圈寄存器反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----线圈寄存器起始地址H
//buffer[9] = 0x01; //----线圈寄存器起始地址L
//buffer[10] = 0x00; //---设置长度H
//buffer[11] = 0x01; //---设置长度L
#endregion
byte[] addrByte = AddrResolver(addr); //--------------线圈寄存器起始地址数组
byte[] lengthByte = WriteDataResolver(length); //-----设置长度数组
byte count = length % 8 == 0 ? (byte)(length / 8) : (byte)(length / 8 + 1); //----字节长度
byte[] data = WriteDataResolver(value, count); //---------------------------------写入数据
#region 发送指令
/*BIN指令*/
/*写多个线圈寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = (byte)(7 + count); //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.写多个线圈寄存器); //----功能码
buffer[8] = addrByte[0]; //----线圈寄存器起始地址H
buffer[9] = addrByte[1]; //----线圈寄存器起始地址L
buffer[10] = lengthByte[0]; //---设置长度H
buffer[11] = lengthByte[1]; //---设置长度L
buffer[12] = count; //---字节长度
for (int i = 0; i < data.Length; i++)
{
buffer[13 + i] = data[i]; //------设置值
}
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
}
#endregion
#region 写入多个保持寄存器值(D寄存器)
/// <summary>
/// 写入多个保持寄存器值
/// </summary>
/// <param name="ID">客户端ID</param>
/// <param name="addr">地址</param>
/// <param name="length">长度</param>
/// <param name="value">值</param>
public void WriteMultipleRegister(short ID, string addr, int length, string value)
{
#region 写入多个保持寄存器值
/*BIN指令*/
/*写入多个保持寄存器值*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x01; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x03; //----功能码
//buffer[8] = 0x00; //----寄存器起始地址H
//buffer[9] = 0x01; //----寄存器起始地址L
//buffer[10] = 0x00; //---设置长度H
//buffer[11] = 0x01; //---设置长度L
//buffer[12] = 0x01; //---字节个数
//buffer[13] = 0x01; //---设置值1H
//buffer[14] = 0x01; //---设置值1L
//buffer[15] = 0x01; //---设置值2H
//buffer[16] = 0x01; //---设置值2L
#endregion
#region 写入多个保持寄存器反馈
/*写入多个保持寄存器反馈*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x00; //----事务处理标识H--固定值0x00
//buffer[1] = 0x00; //----事务处理标识L--固定值0x00
//buffer[2] = 0x00; //----协议标识H--固定值0x00
//buffer[3] = 0x00; //----协议标识L--固定值0x00
//buffer[4] = 0x00; //----长度H
//buffer[5] = 0x06; //----长度L
//buffer[6] = 0x01; //----单位标识
//buffer[7] = 0x06; //----功能码
//buffer[8] = 0x01; //----寄存器起始地址H
//buffer[9] = 0x01; //----寄存器起始地址L
//buffer[10] = 0x00; //---设置长度H
//buffer[11] = 0x01; //---设置长度L
#endregion
byte[] addrByte = AddrResolver(addr); //----------------寄存器起始地址数组
byte[] lenghtBuffer = WriteDataResolver(length); //-----寄存器个数数组
byte[] data = WriteDataResolver(value, 2 * length); //--------------写入数据
#region 发送指令
/*BIN指令*/
/*写多个保持寄存器指令*/
buffer[0] = 0x00; //----事务处理标识H--固定值0x00
buffer[1] = 0x01; //----事务处理标识L--固定值0x00
buffer[2] = 0x00; //----协议标识H--固定值0x00
buffer[3] = 0x00; //----协议标识L--固定值0x00
buffer[4] = 0x00; //----长度H
buffer[5] = (byte)(7 + 2 * length); //----长度L
buffer[6] = (byte)ID; //----单位标识--一般为0x01
buffer[7] = Convert.ToByte((short)Comand.写多个保持寄存器); //----功能码
buffer[8] = addrByte[0]; //----寄存器首地址H
buffer[9] = addrByte[1]; //----寄存器首地址L
buffer[10] = lenghtBuffer[0]; //---设定长度H
buffer[11] = lenghtBuffer[1]; //---设定长度L
buffer[12] = (byte)(2 * length); //---字节个数
for (int i = 0; i < data.Length; i++)
{
buffer[13 + i] = data[i]; //------设置值
}
#endregion
#region 发送
try
{
ClientSocket.Send(buffer, 6 + buffer[5], SocketFlags.None); //----发送
}
catch { }
#endregion
}
#endregion
#region 写入数据解析
/// <summary>
/// 写入数据解析
/// </summary>
/// <param name="data">字符数据</param>
/// <returns>返回byte数组</returns>
private byte[] WriteDataResolver(string data, int length)
{
#region 以前公式-屏蔽
//byte[] dataBuffer = new byte[2];
//int data1, data2;
//long data_long = Convert.ToInt64(data);
//data1 = (int)data_long % 256;
//data2 = (int)data_long / 256;
//if (data2 > 255)
// data2 = data2 % 255;
//dataBuffer[0] = Convert.ToByte(data2);
//dataBuffer[1] = Convert.ToByte(data1);
//return dataBuffer;
#endregion
byte[] dataBuffer = new byte[length];
long data_long = Convert.ToInt64(data);
if (data_long < 0)
{
data_long = Math.Abs(data_long);
data_long = GetComplementer(data_long, length);
}
for (int i = 0; i < length; i++)
{
#region 以前公式
//dataBuffer[length - 1 - i] = Convert.ToByte(data_long % 256); //---倒序(低位在前,高位在后)
#endregion
dataBuffer[i] = Convert.ToByte(data_long % 256); //---正序(高位在前,低位在后)
data_long = data_long / 256;
}
#region 高底位互换
byte buffer = 0;
for (int i = 0; i < length / 2; i++)
{
buffer = dataBuffer[2 * i];
dataBuffer[2 * i] = dataBuffer[2 * i + 1];
dataBuffer[2 * i + 1] = buffer;
}
#endregion
return dataBuffer;
}
/// <summary>
/// 写入数据解析
/// </summary>
/// <param name="data">整数数据</param>
/// <param name="length">字节长度</param>
/// <returns>返回byte数组</returns>
private byte[] WriteDataResolver(int data, int length = 2)
{
byte[] dataBuffer = new byte[length];
long data_long = Convert.ToInt64(data);
if (data_long < 0)
{
data_long = Math.Abs(data_long);
data_long = GetComplementer(data_long, length);
}
for (int i = 0; i < length; i++)
{
dataBuffer[length - 1 - i] = Convert.ToByte(data_long % 256);
data_long = data_long / 256;
}
return dataBuffer;
}
#endregion
#region 负数求补码
/// <summary>
/// 负数求补码long类型
/// </summary>
/// <param name="data">数据</param>
/// <param name="length">长度</param>
/// <returns></returns>
private long GetComplementer(long data, int length)
{
long lData = 0;
switch (length)
{
case 2: //------字
lData = data ^ 0xFFFF;
lData++;
break;
case 4: //------双字
lData = data ^ 0xFFFFFFFF;
lData++;
break;
}
return lData;
}
#endregion
#region ModubusTCP协议数据接收--开启一个新线程负责不停的接收服务器发过来的数据
/// <summary>
/// 数据接收
/// </summary>
private void Receive()
{
while (true)
{
try
{
byte[] buffer = new byte[255];
int r = ClientSocket.Receive(buffer);
stopTime2 = DateTime.Now;
info.msg = "接收时间(毫秒):" + stopTime2.Subtract(stopTime1).Milliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
data = ReceiveResolver(buffer);
string newBuffer = "";
for (int i = 0; i < r; i++)
{
newBuffer += buffer[i].ToString("x") + " ";
}
info.msg = "反馈数据:" + newBuffer;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
stopTime3 = DateTime.Now;
info.msg = "解析时间(毫秒):" + stopTime3.Subtract(stopTime2).Milliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
Disconnect(); //------------断开连接
//if (buffer[8] <= 2) /*判断数据读取命令或写入反馈*/
//{
// /*数据读取命令*/
// string dataStr = buffer[9].ToString("x") + buffer[10].ToString("x");
// state = "16进制:" + dataStr + "";
// Infomation(state); /*回调方法---状态显示*/
// int dataInt = int.Parse(dataStr, System.Globalization.NumberStyles.HexNumber);
// state = "10进制:" + dataInt + "";
// Infomation(state); /*回调方法---状态显示*/
//}
//else
//{
// /*写入反馈*/
// state = "反馈:" + newBuffer + "";
// Infomation(state); /*回调方法---状态显示*/
//}
//Thread.Sleep(5);
}
catch (Exception e)
{
//Infomation(e.ToString()); /*回调方法---状态显示*/
}
}
}
#endregion
#region 接收数据解析
/// <summary>
/// 接收数据解析
/// </summary>
/// <param name="buffer">接收到byte数组</param>
/// <returns>byte数组</returns>
public byte[] ReceiveResolver(byte[] buffer)
{
byte[] dataBuffer = null;
int length = 1;
if (buffer[5] > 3) //---------------数据长度
{
length = (int)buffer[8]; //-----字节数
dataBuffer = new byte[length];
switch (buffer[7]) //-----------功能码
{
case (byte)Comand.读线圈寄存器: //-------------功能:0x01
for (int i = 0; i < length; i++)
{
dataBuffer[i] = buffer[9 + i];
}
break;
case (byte)Comand.读输入状态: //-------------功能:0x02
for (int i = 0; i < length; i++)
{
dataBuffer[i] = buffer[9 + i];
}
break;
case (byte)Comand.读保存寄存器: //-----------功能:0x03
for (int i = 0; i < length; i++)
{
dataBuffer[i] = buffer[9 + i];
}
break;
case (byte)Comand.读输入寄存器: //-----------功能:0x04
for (int i = 0; i < length; i++)
{
dataBuffer[i] = buffer[9 + i];
}
break;
}
}
return dataBuffer;
}
#endregion
}
#endregion优化代码稳定性,保持变量和方法命名不变。修复长时间无沟通连接中断Bug始化功能的分析与优化
最新发布