qq_34725366 2016-04-20 02:26 采纳率: 0%
浏览 8342

远程主机强迫关闭了一个现有的连接,求助~

问题是发生在我的客户端和服务器端之间进行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这个工具发送的请求能正常收到请求后服务器返回的数据,请问这个原因是什么?

  • 写回答

1条回答

  • pshl7 2023-07-13 11:21
    关注

    请问解决了没有,我现在也遇到同样的问题,求答案。

    评论

报告相同问题?

悬赏问题

  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥15 MCNP里如何定义多个源?
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services