问题是发生在我的客户端和服务器端之间进行Modbus TCP通讯的时候。代码如下:
internal class ModbusTcpIpWrapper : ModbusWrapper, IDisposable
{
public static ModbusTcpIpWrapper Instance = new ModbusTcpIpWrapper();
private ModbusSocketWrapper socketWrapper = new ModbusSocketWrapper();
public bool Connected = false;
#region modbus tcp连接
public override void Connect(string ip)
{
if (!Connected)
{
this.socketWrapper.Logger = Logger;
this.socketWrapper.Connect(ip);
this.Connected = true;
}
}
#endregion
#region 读取Modbus寄存器数据
public override byte[] Receive(string ip, byte functionCode, UInt16 startAddress, short registerNum, int bufferSize)
{
Connect(ip);
List<byte> sendData = new List<byte>(255); //申请一个255个字节空间的List
//发送Modbus请求ADU编码
sendData.AddRange(ModbusValueHelper.Instance.GetBytes(this.NextDataIndex())); //事务ID标识
sendData.AddRange(new Byte[] { 0, 0 }); //Protocal Identifier(协议标识),Modbus中此值为0
sendData.AddRange(ModbusValueHelper.Instance.GetBytes((short)6)); //后续的Byte数量(针对读请求,后续为6个byte)
sendData.Add((byte)0); //Unit Identifier(单元标识符):用于系统间的路由
sendData.Add((byte)functionCode); //读取寄存器中的值
sendData.AddRange(ModbusValueHelper.Instance.GetBytes((Int16)startAddress)); //起始地址
sendData.AddRange(ModbusValueHelper.Instance.GetBytes((short)registerNum)); //需要读取寄存器的数量
this.socketWrapper.Write(sendData.ToArray()); //发送读请求
//防止连续读写引起前台的UI线程堵塞
Application.DoEvents();
//读取Response Header:完后会返回8个byte的Response Header
byte[] receiveData = socketWrapper.Read(bufferSize, ip); //缓冲区中的数量不超过256byte,一次读256byte,防止残余数据影响下次读取
short identifier = (short)((((short)receiveData[0]) << 8) + receiveData[1]);
//读取返回数据:根据Response Header,读取后续的数据
if (identifier != CurrentDataIndex) //请求的数据标识与返回的标识不一致,则丢掉数据包
{
return new Byte[0];
}
byte length = receiveData[8]; //最后一个字节,记录寄存器中数据的Byte数
byte[] result = new byte[length];
Array.Copy(receiveData, 9, result, 0, length); //从指定的索引源开始,复制receiveData中的一系列数据到result中(从指定目标的索引开始)
return result;
}
#endregion
internal class ModbusSocketWrapper : IDisposable
{
private static int Port = Int32.Parse(ConfigurationManager.AppSettings["Port"]); //数据传输的端口号Port,Modbus TCP规定为502
private static int Timeout = Int32.Parse(ConfigurationManager.AppSettings["SocketTimeout"]); //设置数据发送超时时间
public IModbusLog Logger { get; set; }
public Socket Socket = null;
#region 建立Socket连接
/// <summary>
/// 创建一个基于TCP上的Socket
/// 实现Socket端口复用
/// 将服务器主机的IP地址与端口号组合
/// 建立与远程主机的连接
/// </summary>
public void Connect(string ip)
{
this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, Timeout);
IPEndPoint ipConnect = new IPEndPoint(IPAddress.Parse(ip), Port);
this.Socket.Connect(ipConnect);
}
#endregion
#region 读取数据
public byte[] Read(int length, string ipGet)
{
byte[] data = new byte[length];
//while (true)
//{
try
{
Socket.Receive(data);
Log("Receive:", data);
return data;
}
catch (Exception ex)
{
string ep = ex.ToString();
Socket.Close();
Connect(ipGet);
//MessageBox.Show(ep);
return null;
}
//}
}
#endregion
#region 写入数据
public void Write(byte[] data)
{
try
{
Log("Send:", data);
Socket.Send(data);
}
catch (Exception ex)
{
string ep = ex.ToString();
//MessageBox.Show(ep);
}
}
#endregion
#region 记录数据
public void Log(string type, byte[] data)
{
if (Logger != null)
{
//创建一个新的可变字符字符串对象
StringBuilder logText = new StringBuilder(type);
//将数据中的每一个byte量
foreach (byte item in data)
{
//将括号内的item转化成字符串表示形式添加到当前对象表示的字符串结尾处
logText.Append(item.ToString() + "");
}
Logger.Write(logText.ToString());
}
}
#endregion
#region IDisponsable 成员
public void Dispose()
{
if (Socket != null)
{
Socket.Close();
}
}
#endregion
}
当我运行时,就会出现下面的问题
我将我发送的请求和Modbuspull这个工具发送的请求进行了对比,是一样的,但是我的请求会被拒绝,而Modbuspull这个工具发送的请求能正常收到请求后服务器返回的数据,请问这个原因是什么?