Exemple #1
0
 /// <summary>
 /// 重新开始接收下一次的数据传递
 /// </summary>
 /// <param name="session">网络状态</param>
 /// <param name="isProcess">是否触发数据处理</param>
 internal void ReBeginReceiveHead(AppSession session, bool isProcess)
 {
     try
     {
         byte[] head = session.BytesHead, Content = session.BytesContent;
         session.Clear( );
         session.WorkSocket.BeginReceive(session.BytesHead, session.AlreadyReceivedHead, session.BytesHead.Length - session.AlreadyReceivedHead,
                                         SocketFlags.None, new AsyncCallback(HeadBytesReceiveCallback), session);
         // 检测是否需要数据处理
         if (isProcess)
         {
             // 校验令牌
             if (CheckRemoteToken(head))
             {
                 Content = HslProtocol.CommandAnalysis(head, Content);
                 int protocol = BitConverter.ToInt32(head, 0);
                 int customer = BitConverter.ToInt32(head, 4);
                 // 转移到数据中心处理
                 DataProcessingCenter(session, protocol, customer, Content);
             }
             else
             {
                 // 应该关闭网络通信
                 LogNet?.WriteWarn(ToString( ), StringResources.TokenCheckFailed);
                 AppSessionRemoteClose(session);
             }
         }
     }
     catch (Exception ex)
     {
         SocketReceiveException(session, ex);
         LogNet?.WriteException(ToString( ), ex);
     }
 }
Exemple #2
0
        /// <summary>
        /// 处理请求接收连接后的方法
        /// </summary>
        /// <param name="obj">Accpt对象</param>
        protected override void ThreadPoolLogin(object obj)
        {
            if (obj is Socket socket)
            {
                // 接收一条信息,指定当前请求的数据订阅信息的关键字
                OperateResult <int, string> receive = ReceiveStringContentFromSocket(socket);
                if (!receive.IsSuccess)
                {
                    return;
                }

                // 判断当前的关键字在服务器是否有消息发布
                if (!IsPushGroupOnline(receive.Content2))
                {
                    SendStringAndCheckReceive(socket, 1, "当前订阅的关键字不存在");
                    LogNet?.WriteWarn(ToString( ), "当前订阅的关键字不存在");
                    socket?.Close( );
                    return;
                }

                SendStringAndCheckReceive(socket, 0, "");

                // 允许发布订阅信息
                AppSession session = new AppSession( );
                session.KeyGroup   = receive.Content2;
                session.WorkSocket = socket;
                try
                {
                    session.IpEndPoint = (System.Net.IPEndPoint)socket.RemoteEndPoint;
                    session.IpAddress  = session.IpEndPoint.Address.ToString( );
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString( ), "Ip信息获取失败", ex);
                }

                try
                {
                    socket.BeginReceive(session.BytesHead, 0, session.BytesHead.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), session);
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString( ), "开启信息接收失败", ex);
                    return;
                }

                LogNet?.WriteDebug(ToString( ), $"客户端 [ {session.IpEndPoint} ] 上线");
                PushGroupClient push = GetPushGroupClient(receive.Content2);
                if (push != null)
                {
                    System.Threading.Interlocked.Increment(ref onlineCount);
                    push.AddPushClient(session);
                }
            }
        }
        private void ReceiveCallBack(IAsyncResult ar)
        {
            if (ar.AsyncState is Socket socket)
            {
                try
                {
                    int receive = socket.EndReceive(ar);
                    OperateResult <byte[]> read = RedisHelper.ReceiveCommand(socket);
                    if (!read.IsSuccess)
                    {
                        SocketReceiveException(null);
                        return;
                    }
                    else
                    {
                        socket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
                    }

                    OperateResult <string[]> data = RedisHelper.GetStringsFromCommandLine(read.Content);
                    if (!data.IsSuccess)
                    {
                        LogNet?.WriteWarn(data.Message);
                        return;
                    }

                    if (data.Content[0].ToUpper() == "SUBSCRIBE")
                    {
                        return;
                    }
                    else if (data.Content[0].ToUpper( ) == "MESSAGE")
                    {
                        action?.Invoke(data.Content[1], data.Content[2]);
                    }
                    else
                    {
                        LogNet?.WriteWarn(data.Content[0]);
                    }
                }
                catch (ObjectDisposedException)
                {
                    // 通常是主动退出
                    return;
                }
                catch (Exception ex)
                {
                    SocketReceiveException(ex);
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// [自校验] 从套接字中接收文件头信息
        /// </summary>
        /// <param name="socket"></param>
        /// <returns></returns>
        protected OperateResult <FileBaseInfo> ReceiveFileHeadFromSocket(Socket socket)
        {
            // 先接收文件头信息
            OperateResult <int, string> receiveString = ReceiveStringContentFromSocket(socket);

            if (!receiveString.IsSuccess)
            {
                return(new OperateResult <FileBaseInfo>( )
                {
                    Message = receiveString.Message
                });
            }

            // 判断文件是否存在
            if (receiveString.Content1 == 0)
            {
                socket?.Close( );
                LogNet?.WriteWarn(ToString( ), "对方文件不存在,无法接收!");
                return(new OperateResult <FileBaseInfo>( )
                {
                    Message = StringResources.FileNotExist
                });
            }

            OperateResult <FileBaseInfo> result = new OperateResult <FileBaseInfo>( );

            result.Content = new FileBaseInfo( );
            try
            {
                // 提取信息
                Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(receiveString.Content2);
                result.Content.Name   = SoftBasic.GetValueFromJsonObject(json, "FileName", "");
                result.Content.Size   = SoftBasic.GetValueFromJsonObject(json, "FileSize", 0L);
                result.Content.Tag    = SoftBasic.GetValueFromJsonObject(json, "FileTag", "");
                result.Content.Upload = SoftBasic.GetValueFromJsonObject(json, "FileUpload", "");
                result.IsSuccess      = true;
            }
            catch (Exception ex)
            {
                socket?.Close( );
                result.Message = "提取信息失败," + ex.Message;
            }

            return(result);
        }
Exemple #5
0
 /// <summary>
 /// 检查网络套接字是否操作超时,需要对套接字进行封装
 /// </summary>
 /// <param name="obj">通常是 <see cref="HslTimeOut"/> 对象 </param>
 protected void ThreadPoolCheckTimeOut(object obj)
 {
     if (obj is HslTimeOut timeout)
     {
         while (!timeout.IsSuccessful)
         {
             Thread.Sleep(100);
             if ((DateTime.Now - timeout.StartTime).TotalMilliseconds > timeout.DelayTime)
             {
                 // 连接超时或是验证超时
                 if (!timeout.IsSuccessful)
                 {
                     LogNet?.WriteWarn(ToString( ), "Wait Time Out : " + timeout.DelayTime);
                     timeout.Operator?.Invoke( );
                     timeout.WorkSocket?.Close( );
                 }
                 break;
             }
         }
     }
 }
        /// <summary>
        /// 接收到串口数据的时候触发
        /// </summary>
        /// <param name="sender">串口对象</param>
        /// <param name="e">消息</param>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(20);              // 此处做个微小的延时,等待数据接收完成

            byte[] buffer = new byte[1024];
            int    count  = serialPort.Read(buffer, 0, serialPort.BytesToRead);

            byte[] receive = new byte[count];
            Array.Copy(buffer, 0, receive, 0, count);

            if (receive.Length < 3)
            {
                LogNet?.WriteError(ToString( ), $"Uknown Data:" + BasicFramework.SoftBasic.ByteToHexString(receive, ' '));
                return;
            }

            if (Serial.SoftCRC16.CheckCRC16(receive))
            {
                byte[] modbusCore = ModbusRtuTransModbusCore(receive);


                if (!CheckModbusMessageLegal(modbusCore))
                {
                    // 指令长度验证错误,关闭网络连接
                    LogNet?.WriteError(ToString( ), $"Receive Nosense Modbus-tcp : " + BasicFramework.SoftBasic.ByteToHexString(receive, ' '));
                    return;
                }

                // LogNet?.WriteError( ToString( ), $"Success:" + BasicFramework.SoftBasic.ByteToHexString( receive, ' ' ) );
                // 需要回发消息
                byte[] copy = ModbusCoreTransModbusRtu(ReadFromModbusCore(modbusCore));

                serialPort.Write(copy, 0, copy.Length);
            }
            else
            {
                LogNet?.WriteWarn("CRC Check Failed : " + BasicFramework.SoftBasic.ByteToHexString(receive, ' '));
            }
        }
Exemple #7
0
        private void ThreadHeartCheck( )
        {
            while (true)
            {
                Thread.Sleep(2000);

                try
                {
                    for (int i = appSessions.Count - 1; i >= 0; i--)
                    {
                        if (appSessions[i] == null)
                        {
                            appSessions.RemoveAt(i);
                            continue;
                        }

                        if ((DateTime.Now - appSessions[i].HeartTime).TotalSeconds > 1 * 8)//8次没有收到失去联系
                        {
                            LogNet?.WriteWarn(ToString(), "心跳验证超时,强制下线:" + appSessions[i].IpAddress.ToString( ));
                            TcpStateDownLine(appSessions[i], false, false);
                            continue;
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString(), "心跳线程异常:", ex);
                }


                if (!IsStarted)
                {
                    break;
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// 登录后的处理方法
        /// </summary>
        /// <param name="obj"></param>
        protected override void ThreadPoolLogin(object obj)
        {
            if (obj is Socket socket)
            {
                // 判断连接数是否超出规定
                if (appSessions.Count > ConnectMax)
                {
                    socket?.Close( );
                    LogNet?.WriteWarn(ToString(), StringResources.NetClientFull);
                    return;
                }

                // 接收用户别名并验证令牌
                OperateResult result = new OperateResult( );
                OperateResult <int, string> readResult = ReceiveStringContentFromSocket(socket);
                if (!readResult.IsSuccess)
                {
                    return;
                }

                // 登录成功
                AppSession session = new AppSession( )
                {
                    WorkSocket = socket,
                    LoginAlias = readResult.Content2,
                };


                try
                {
                    session.IpEndPoint = (IPEndPoint)socket.RemoteEndPoint;
                    session.IpAddress  = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString( );
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString( ), "客户端地址获取失败:", ex);
                }

                if (readResult.Content1 == 1)
                {
                    // 电脑端客户端
                    session.ClientType = "Windows";
                }
                else if (readResult.Content1 == 2)
                {
                    // Android 客户端
                    session.ClientType = "Android";
                }


                try
                {
                    session.WorkSocket.BeginReceive(session.BytesHead, session.AlreadyReceivedHead,
                                                    session.BytesHead.Length - session.AlreadyReceivedHead, SocketFlags.None,
                                                    new AsyncCallback(HeadBytesReceiveCallback), session);
                    TcpStateUpLine(session);
                    Thread.Sleep(100);  //留下一些时间进行反应
                }
                catch (Exception ex)
                {
                    //登录前已经出错
                    TcpStateClose(session);
                    LogNet?.WriteException(ToString(), StringResources.NetClientLoginFailed, ex);
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// 指令头接收方法
        /// </summary>
        /// <param name="ar">异步状态信息</param>
        protected void HeadBytesReceiveCallback(IAsyncResult ar)
        {
            if (ar.AsyncState is AppSession session)
            {
                try
                {
                    int receiveCount = session.WorkSocket.EndReceive(ar);
                    if (receiveCount == 0)
                    {
                        // 断开了连接,需要做个处理,一个是直接关闭,另一个是触发下线
                        AppSessionRemoteClose(session);
                        return;
                    }
                    else
                    {
                        session.AlreadyReceivedHead += receiveCount;
                    }
                }
                catch (ObjectDisposedException)
                {
                    // 不需要处理,来自服务器主动关闭
                    return;
                }
                catch (SocketException ex)
                {
                    // 已经断开连接了
                    SocketReceiveException(session, ex);
                    LogNet?.WriteException(ToString( ), ex);
                    return;
                }
                catch (Exception ex)
                {
                    // 其他乱七八糟的异常重新启用接收数据
                    ReBeginReceiveHead(session, false);
                    LogNet?.WriteException(ToString( ), StringResources.SocketEndReceiveException, ex);
                    return;
                }


                if (session.AlreadyReceivedHead < session.BytesHead.Length)
                {
                    try
                    {
                        // 仍需要接收
                        session.WorkSocket.BeginReceive(session.BytesHead, session.AlreadyReceivedHead, session.BytesHead.Length - session.AlreadyReceivedHead,
                                                        SocketFlags.None, new AsyncCallback(HeadBytesReceiveCallback), session);
                    }
                    catch (Exception ex)
                    {
                        SocketReceiveException(session, ex);
                        LogNet?.WriteException(ToString( ), ex);
                    }
                }
                else
                {
                    // 接收完毕,校验令牌
                    if (!CheckRemoteToken(session.BytesHead))
                    {
                        LogNet?.WriteWarn(ToString( ), StringResources.TokenCheckFailed);
                        AppSessionRemoteClose(session);
                        return;
                    }

                    int receive_length = BitConverter.ToInt32(session.BytesHead, session.BytesHead.Length - 4);


                    session.BytesContent = new byte[receive_length];

                    if (receive_length > 0)
                    {
                        try
                        {
                            int receiveSize = session.BytesContent.Length - session.AlreadyReceivedContent;
                            session.WorkSocket.BeginReceive(session.BytesContent, session.AlreadyReceivedContent, receiveSize,
                                                            SocketFlags.None, new AsyncCallback(ContentReceiveCallback), session);
                        }
                        catch (Exception ex)
                        {
                            SocketReceiveException(session, ex);
                            LogNet?.WriteException(ToString( ), ex);
                        }
                    }
                    else
                    {
                        // 处理数据并重新启动接收
                        ReBeginReceiveHead(session, true);
                    }
                }
            }
        }
Exemple #10
0
        private void AsyncCallback(IAsyncResult ar)
        {
            if (ar.AsyncState is AsyncStateOne state)
            {
                try
                {
                    int received = state.WorkSocket.EndReceiveFrom(ar, ref state.UdpEndPoint);
                    //释放连接关联
                    state.WorkSocket = null;
                    //马上开始重新接收,提供性能保障
                    RefreshReceive();
                    //处理数据
                    if (received >= HslCommunicationCode.HeadByteLength)
                    {
                        //检测令牌
                        if (NetSupport.IsTwoBytesEquel(state.BytesContent, 12, KeyToken.ToByteArray(), 0, 16))
                        {
                            state.IpEndPoint = (IPEndPoint)state.UdpEndPoint;
                            int contentLength = BitConverter.ToInt32(state.BytesContent, HslCommunicationCode.HeadByteLength - 4);
                            if (contentLength == received - HslCommunicationCode.HeadByteLength)
                            {
                                byte[] head    = new byte[HslCommunicationCode.HeadByteLength];
                                byte[] content = new byte[contentLength];

                                Array.Copy(state.BytesContent, 0, head, 0, HslCommunicationCode.HeadByteLength);
                                if (contentLength > 0)
                                {
                                    Array.Copy(state.BytesContent, 32, content, 0, contentLength);
                                }

                                //解析内容
                                content = NetSupport.CommandAnalysis(head, content);

                                int protocol = BitConverter.ToInt32(head, 0);
                                int customer = BitConverter.ToInt32(head, 4);
                                //丢给数据中心处理
                                DataProcessingCenter(state, protocol, customer, content);
                            }
                            else
                            {
                                //否则记录到日志
                                LogNet?.WriteWarn(LogHeaderText, $"接收到异常数据,应接收长度:{(BitConverter.ToInt32(state.BytesContent, 4) + 8)} 实际接收:{received}");
                            }
                        }
                        else
                        {
                            LogNet?.WriteWarn(LogHeaderText, StringResources.TokenCheckFailed);
                        }
                    }
                    else
                    {
                        LogNet?.WriteWarn(LogHeaderText, $"接收到异常数据,长度不符合要求,实际接收:{received}");
                    }
                }
                catch (ObjectDisposedException ex)
                {
                    //主程序退出的时候触发
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(LogHeaderText, StringResources.SocketEndReceiveException, ex);
                    //重新接收,此处已经排除掉了对象释放的异常
                    RefreshReceive();
                }
                finally
                {
                    //state = null;
                }
            }
        }
        private void AsyncCallback(IAsyncResult ar)
        {
            if (ar.AsyncState is AppSession session)
            {
                try
                {
                    int received = session.WorkSocket.EndReceiveFrom(ar, ref session.UdpEndPoint);
                    // 释放连接关联
                    session.WorkSocket = null;
                    // 马上开始重新接收,提供性能保障
                    RefreshReceive( );
                    // 处理数据
                    if (received >= HslProtocol.HeadByteLength)
                    {
                        // 检测令牌
                        if (CheckRemoteToken(session.BytesContent))
                        {
                            session.IpEndPoint = (IPEndPoint)session.UdpEndPoint;
                            int contentLength = BitConverter.ToInt32(session.BytesContent, HslProtocol.HeadByteLength - 4);
                            if (contentLength == received - HslProtocol.HeadByteLength)
                            {
                                byte[] head    = new byte[HslProtocol.HeadByteLength];
                                byte[] content = new byte[contentLength];

                                Array.Copy(session.BytesContent, 0, head, 0, HslProtocol.HeadByteLength);
                                if (contentLength > 0)
                                {
                                    Array.Copy(session.BytesContent, 32, content, 0, contentLength);
                                }

                                // 解析内容
                                content = HslProtocol.CommandAnalysis(head, content);

                                int protocol = BitConverter.ToInt32(head, 0);
                                int customer = BitConverter.ToInt32(head, 4);
                                // 丢给数据中心处理
                                DataProcessingCenter(session, protocol, customer, content);
                            }
                            else
                            {
                                // 否则记录到日志
                                LogNet?.WriteWarn(ToString(), $"Should Rece:{(BitConverter.ToInt32( session.BytesContent, 4 ) + 8)} Actual:{received}");
                            }
                        }
                        else
                        {
                            LogNet?.WriteWarn(ToString( ), StringResources.Language.TokenCheckFailed);
                        }
                    }
                    else
                    {
                        LogNet?.WriteWarn(ToString( ), $"Receive error, Actual:{received}");
                    }
                }
                catch (ObjectDisposedException)
                {
                    //主程序退出的时候触发
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString( ), StringResources.Language.SocketEndReceiveException, ex);
                    //重新接收,此处已经排除掉了对象释放的异常
                    RefreshReceive( );
                }
                finally
                {
                    //state = null;
                }
            }
        }
        /// <summary>
        /// 处理请求接收连接后的方法
        /// </summary>
        /// <param name="obj">Accpt对象</param>
        protected override void ThreadPoolLogin(object obj)
        {
            if (obj is Socket socket)
            {
                // 接收一条信息,指定当前请求的数据订阅信息的关键字
                OperateResult <int, string> receive = ReceiveStringContentFromSocket(socket);
                if (!receive.IsSuccess)
                {
                    return;
                }

                // 判断当前的关键字在服务器是否有消息发布
                if (!IsPushGroupOnline(receive.Content2))
                {
                    SendStringAndCheckReceive(socket, 1, StringResources.Language.KeyIsNotExist);
                    LogNet?.WriteWarn(ToString( ), StringResources.Language.KeyIsNotExist);
                    socket?.Close( );
                    return;
                }

                SendStringAndCheckReceive(socket, 0, "");

                // 允许发布订阅信息
                AppSession session = new AppSession
                {
                    KeyGroup   = receive.Content2,
                    WorkSocket = socket
                };

                try
                {
                    session.IpEndPoint = (System.Net.IPEndPoint)socket.RemoteEndPoint;
                    session.IpAddress  = session.IpEndPoint.Address.ToString( );
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString( ), StringResources.Language.GetClientIpaddressFailed, ex);
                }

                try
                {
                    socket.BeginReceive(session.BytesHead, 0, session.BytesHead.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), session);
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString( ), StringResources.Language.SocketReceiveException, ex);
                    return;
                }

                LogNet?.WriteDebug(ToString( ), string.Format(StringResources.Language.ClientOnlineInfo, session.IpEndPoint));
                PushGroupClient push = GetPushGroupClient(receive.Content2);
                if (push != null)
                {
                    System.Threading.Interlocked.Increment(ref onlineCount);
                    push.AddPushClient(session);

                    dicSendCacheLock.Enter( );
                    if (dictSendHistory.ContainsKey(receive.Content2))
                    {
                        if (isPushCacheAfterConnect)
                        {
                            SendString(session, dictSendHistory[receive.Content2]);
                        }
                    }
                    dicSendCacheLock.Leave( );
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// 登录后的处理方法
        /// </summary>
        /// <param name="obj"></param>
        protected override void ThreadPoolLogin(object obj)
        {
            if (obj is Socket socket)
            {
                // 判断连接数是否超出规定
                if (All_sockets_connect.Count > ConnectMax)
                {
                    socket?.Close();
                    LogNet?.WriteWarn(LogHeaderText, StringResources.NetClientFull);
                    return;
                }

                // 接收用户别名并验证令牌
                OperateResult result = new OperateResult();
                if (!ReceiveStringFromSocket(
                        socket,
                        out int customer,
                        out string login_alias,
                        result,
                        null
                        ))
                {
                    socket?.Close();
                    return;
                }



                // 登录成功
                AsyncStateOne stateone = new AsyncStateOne()
                {
                    WorkSocket = socket,
                    LoginAlias = login_alias,
                    IpEndPoint = (IPEndPoint)socket.RemoteEndPoint,
                    IpAddress  = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString(),
                };


                if (customer == 1)
                {
                    // 电脑端客户端
                    stateone.ClientType = "Windows";
                }
                else if (customer == 2)
                {
                    // Android 客户端
                    stateone.ClientType = "Android";
                }


                try
                {
                    stateone.WorkSocket.BeginReceive(stateone.BytesHead, stateone.AlreadyReceivedHead,
                                                     stateone.BytesHead.Length - stateone.AlreadyReceivedHead, SocketFlags.None,
                                                     new AsyncCallback(HeadReceiveCallback), stateone);
                    TcpStateUpLine(stateone);
                    Thread.Sleep(500);//留下一些时间进行反应
                }
                catch (Exception ex)
                {
                    //登录前已经出错
                    TcpStateClose(stateone);
                    LogNet?.WriteException(LogHeaderText, StringResources.NetClientLoginFailed, ex);
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// 接收到串口数据的时候触发
        /// </summary>
        /// <param name="sender">串口对象</param>
        /// <param name="e">消息</param>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int rCount = 0;

            byte[] buffer  = new byte[1024];
            byte[] receive = null;

            while (true)
            {
                System.Threading.Thread.Sleep(20);              // 此处做个微小的延时,等待数据接收完成
                int count = serialPort.Read(buffer, rCount, serialPort.BytesToRead);
                rCount += count;
                if (count == 0)
                {
                    break;
                }

                receive = new byte[rCount];
                Array.Copy(buffer, 0, receive, 0, count);
            }

            if (receive == null)
            {
                return;
            }

            if (receive.Length < 3)
            {
                LogNet?.WriteError(ToString( ), $"Uknown Data:" + SoftBasic.ByteToHexString(receive, ' '));
                return;
            }

            if (Serial.SoftCRC16.CheckCRC16(receive))
            {
                byte[] modbusCore = SoftBasic.BytesArrayRemoveLast(receive, 2);

                if (!CheckModbusMessageLegal(modbusCore))
                {
                    // 指令长度验证错误,关闭网络连接
                    LogNet?.WriteError(ToString( ), $"Receive Nosense Modbus-rtu : " + SoftBasic.ByteToHexString(receive, ' '));
                    return;
                }

                // 验证站号是否一致
                if (station >= 0 && station != modbusCore[0])
                {
                    LogNet?.WriteError(ToString( ), $"Station not match Modbus-rtu : " + SoftBasic.ByteToHexString(receive, ' '));
                    return;
                }

                // LogNet?.WriteError( ToString( ), $"Success:" + BasicFramework.SoftBasic.ByteToHexString( receive, ' ' ) );
                // 需要回发消息
                byte[] copy = ModbusInfo.PackCommandToRtu(ReadFromModbusCore(modbusCore));

                serialPort.Write(copy, 0, copy.Length);

                if (IsStarted)
                {
                    RaiseDataReceived(receive);
                }
            }
            else
            {
                LogNet?.WriteWarn("CRC Check Failed : " + SoftBasic.ByteToHexString(receive, ' '));
            }
        }
        private void ContentReveiveCallBack(IAsyncResult ar)
        {
            if (ar.AsyncState is ModBusState state)
            {
                try
                {
                    int count = state.WorkSocket.EndReceive(ar);

                    state.ContentReceivedLength += count;
                    if (state.ContentReceivedLength < state.Content.Length)
                    {
                        // 数据不够,继续接收
                        state.WorkSocket.BeginReceive(state.Content, state.ContentReceivedLength, state.Content.Length - state.ContentReceivedLength,
                                                      SocketFlags.None, new AsyncCallback(ContentReveiveCallBack), state);
                    }
                    else
                    {
                        // 内容接收完成,所有的数据接收结束
                        byte[] data = new byte[state.HeadByte.Length + state.Content.Length];
                        state.HeadByte.CopyTo(data, 0);
                        state.Content.CopyTo(data, state.HeadByte.Length);

                        state.Clear();

                        // 重新启动接收
                        state.WorkSocket.BeginReceive(state.HeadByte, state.HeadByteReceivedLength, state.HeadByte.Length, SocketFlags.None, new AsyncCallback(HeadReveiveCallBack), state);

                        // 需要回发消息
                        byte[] copy = null;
                        switch (data[7])
                        {
                        case 0x01:
                        {
                            // 线圈读取
                            int address = data[8] * 256 + data[9];
                            int length  = data[10] * 256 + data[11];
                            if (length > 2048)
                            {
                                length = 2048;                                // 线圈读取应该小于2048个
                            }
                            bool[] read   = ReadCoil((ushort)address, (ushort)length);
                            byte[] buffer = BasicFramework.SoftBasic.BoolArrayToByte(read);
                            copy = new byte[9 + buffer.Length];
                            Array.Copy(data, 0, copy, 0, 8);
                            copy[4] = (byte)((copy.Length - 6) / 256);
                            copy[5] = (byte)((copy.Length - 6) % 256);
                            copy[8] = (byte)buffer.Length;
                            Array.Copy(buffer, 0, copy, 9, buffer.Length);
                            break;
                        }

                        case 0x02:
                        {
                            // 离散值读取,本服务器无效
                            copy = new byte[9];
                            Array.Copy(data, 0, copy, 0, 8);
                            copy[4] = 0x00;
                            copy[5] = 0x03;
                            break;
                        }

                        case 0x03:
                        {
                            // 寄存器读取
                            int address = data[8] * 256 + data[9];
                            int length  = data[10] * 256 + data[11];
                            if (length > 127)
                            {
                                length = 127;                                // 寄存器最大读取范围为127个
                            }
                            byte[] buffer = ReadRegister((ushort)address, (ushort)length);
                            copy = new byte[9 + buffer.Length];
                            Array.Copy(data, 0, copy, 0, 8);
                            copy[4] = (byte)((copy.Length - 6) / 256);
                            copy[5] = (byte)((copy.Length - 6) % 256);
                            copy[8] = (byte)buffer.Length;
                            Array.Copy(buffer, 0, copy, 9, buffer.Length);
                            break;
                        }

                        case 0x05:
                        {
                            // 写单个线圈
                            int address = data[8] * 256 + data[9];
                            if (data[10] == 0xFF && data[11] == 0x00)
                            {
                                WriteCoil((ushort)address, true);
                            }
                            else if (data[10] == 0x00 && data[11] == 0x00)
                            {
                                WriteCoil((ushort)address, false);
                            }
                            copy = new byte[12];
                            Array.Copy(data, 0, copy, 0, 12);
                            copy[4] = 0x00;
                            copy[5] = 0x06;
                            break;
                        }

                        case 0x06:
                        {
                            // 写单个寄存器
                            int address = data[8] * 256 + data[9];
                            WriteRegister((ushort)address, data[10], data[11]);
                            copy = new byte[12];
                            Array.Copy(data, 0, copy, 0, 12);
                            copy[4] = 0x00;
                            copy[5] = 0x06;
                            break;
                        }

                        case 0x0F:
                        {
                            // 写多个线圈
                            int    address = data[8] * 256 + data[9];
                            int    length  = data[10] * 256 + data[11];
                            byte[] buffer  = new byte[data.Length - 13];
                            Array.Copy(data, 13, buffer, 0, buffer.Length);
                            bool[] value = BasicFramework.SoftBasic.ByteToBoolArray(buffer, length);
                            WriteCoil((ushort)address, value);
                            copy = new byte[12];
                            Array.Copy(data, 0, copy, 0, 12);
                            copy[4] = 0x00;
                            copy[5] = 0x06;
                            break;
                        }

                        case 0x10:
                        {
                            // 写多个寄存器
                            int    address = data[8] * 256 + data[9];
                            int    length  = data[10] * 256 + data[11];
                            byte[] buffer  = new byte[data.Length - 13];
                            for (int i = 0; i < length; i++)
                            {
                                if ((2 * i + 14) < data.Length)
                                {
                                    WriteRegister((ushort)(address + i), data[2 * i + 13], data[2 * i + 14]);
                                }
                            }
                            copy = new byte[12];
                            Array.Copy(data, 0, copy, 0, 12);
                            copy[4] = 0x00;
                            copy[5] = 0x06;
                            break;
                        }

                        default:
                        {
                            if (IsStarted)
                            {
                                LogNet?.WriteWarn(LogHeaderText, "Unknown Function Code:" + data[7]);
                            }
                            copy = new byte[12];
                            Array.Copy(data, 0, copy, 0, 12);
                            copy[4] = 0x00;
                            copy[5] = 0x06;
                            break;
                        }
                        }

                        // 回发数据
                        state.WorkSocket.BeginSend(copy, 0, size: copy.Length, socketFlags: SocketFlags.None, callback: new AsyncCallback(DataSendCallBack), state: state);

                        // 通知处理消息

                        if (IsStarted)
                        {
                            OnDataReceived?.Invoke(data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    // 关闭连接,记录日志
                    state.WorkSocket?.Close();
                    state = null;
                    if (IsStarted)
                    {
                        LogNet?.WriteException(LogHeaderText, "内容数据接收失败!", ex);
                    }
                }
            }
        }
Exemple #16
0
        private void ModbusDataReveiveCallback(IAsyncResult ar)
        {
            if (ar.AsyncState is ModBusState state)
            {
                try
                {
                    state.ContentReceivedLength += state.WorkSocket.EndReceive(ar);
                }
                catch (Exception ex)
                {
                    // 关闭连接,记录日志
                    state.WorkSocket?.Close();
                    state = null;
                    LogNet?.WriteException(LogHeaderText, "内容数据接收失败!", ex);
                    return;
                }

                if (state.ContentReceivedLength < state.Content.Length)
                {
                    // 数据不够,继续接收
                    state.WorkSocket.BeginReceive(state.Content, state.ContentReceivedLength, state.Content.Length - state.ContentReceivedLength,
                                                  SocketFlags.None, new AsyncCallback(ModbusDataReveiveCallback), state);
                    return;
                }


                // 数据接收完成
                // 内容接收完成,所有的数据接收结束
                byte[] data = new byte[state.HeadByte.Length + state.Content.Length];
                state.HeadByte.CopyTo(data, 0);
                state.Content.CopyTo(data, state.HeadByte.Length);

                state.Clear();



                if (data[7] == 0x01 ||
                    data[7] == 0x02 ||
                    data[7] == 0x03)
                {
                    if (data.Length != 0x0C)
                    {
                        // 指令长度验证错误,关闭网络连接
                        state.WorkSocket?.Close();
                        state = null;
                        LogNet?.WriteWarn(LogHeaderText, "Command length check failed!");
                        return;
                    }
                }



                // 需要回发消息
                byte[] copy = null;
                try
                {
                    switch (data[7])
                    {
                    case 0x01:
                    {
                        // 线圈读取
                        int address = data[8] * 256 + data[9];
                        int length  = data[10] * 256 + data[11];
                        if (length > 2048)
                        {
                            length = 2048;                                // 线圈读取应该小于2048个
                        }
                        bool[] read   = ReadCoil((ushort)address, (ushort)length);
                        byte[] buffer = BasicFramework.SoftBasic.BoolArrayToByte(read);
                        copy = new byte[9 + buffer.Length];
                        Array.Copy(data, 0, copy, 0, 8);
                        copy[4] = (byte)((copy.Length - 6) / 256);
                        copy[5] = (byte)((copy.Length - 6) % 256);
                        copy[8] = (byte)buffer.Length;
                        Array.Copy(buffer, 0, copy, 9, buffer.Length);
                        break;
                    }

                    case 0x03:
                    {
                        // 寄存器读取
                        int address = data[8] * 256 + data[9];
                        int length  = data[10] * 256 + data[11];
                        if (length > 127)
                        {
                            length = 127;                                // 寄存器最大读取范围为127个
                        }
                        byte[] buffer = ReadRegister((ushort)address, (ushort)length);
                        copy = new byte[9 + buffer.Length];
                        Array.Copy(data, 0, copy, 0, 8);
                        copy[4] = (byte)((copy.Length - 6) / 256);
                        copy[5] = (byte)((copy.Length - 6) % 256);
                        copy[8] = (byte)buffer.Length;
                        Array.Copy(buffer, 0, copy, 9, buffer.Length);
                        break;
                    }

                    case 0x05:
                    {
                        // 写单个线圈
                        int address = data[8] * 256 + data[9];
                        if (data[10] == 0xFF && data[11] == 0x00)
                        {
                            WriteCoil((ushort)address, true);
                        }
                        else if (data[10] == 0x00 && data[11] == 0x00)
                        {
                            WriteCoil((ushort)address, false);
                        }
                        copy = new byte[12];
                        Array.Copy(data, 0, copy, 0, 12);
                        copy[4] = 0x00;
                        copy[5] = 0x06;
                        break;
                    }

                    case 0x06:
                    {
                        // 写单个寄存器
                        ushort address  = (ushort)(data[8] * 256 + data[9]);
                        short  ValueOld = ReadShortRegister(address);
                        // 写入到寄存器
                        WriteRegister(address, data[10], data[11]);
                        short ValueNew = ReadShortRegister(address);
                        // 触发写入请求
                        OnRegisterBeforWrite(address, ValueOld, ValueNew);

                        copy = new byte[12];
                        Array.Copy(data, 0, copy, 0, 12);
                        copy[4] = 0x00;
                        copy[5] = 0x06;
                        break;
                    }

                    case 0x0F:
                    {
                        // 写多个线圈
                        int    address = data[8] * 256 + data[9];
                        int    length  = data[10] * 256 + data[11];
                        byte[] buffer  = new byte[data.Length - 13];
                        Array.Copy(data, 13, buffer, 0, buffer.Length);
                        bool[] value = BasicFramework.SoftBasic.ByteToBoolArray(buffer, length);
                        WriteCoil((ushort)address, value);
                        copy = new byte[12];
                        Array.Copy(data, 0, copy, 0, 12);
                        copy[4] = 0x00;
                        copy[5] = 0x06;
                        break;
                    }

                    case 0x10:
                    {
                        // 写多个寄存器
                        int    address = data[8] * 256 + data[9];
                        int    length  = data[10] * 256 + data[11];
                        byte[] buffer  = new byte[data.Length - 13];

                        // 为了使服务器的数据订阅更加的准确,决定将设计改为等待所有的数据写入完成后,再统一触发订阅,2018年3月4日 20:56:47
                        MonitorAddress[] addresses = new MonitorAddress[length];
                        for (int i = 0; i < length; i++)
                        {
                            if ((2 * i + 14) < data.Length)
                            {
                                short ValueOld = ReadShortRegister((ushort)(address + i));
                                WriteRegister((ushort)(address + i), data[2 * i + 13], data[2 * i + 14]);
                                short ValueNew = ReadShortRegister((ushort)(address + i));
                                // 触发写入请求
                                addresses[i] = new MonitorAddress( )
                                {
                                    Address     = (ushort)(address + i),
                                    ValueOrigin = ValueOld,
                                    ValueNew    = ValueNew
                                };
                            }
                        }

                        // 所有数据都更改完成后,再触发消息
                        for (int i = 0; i < addresses.Length; i++)
                        {
                            OnRegisterBeforWrite(addresses[i].Address, addresses[i].ValueOrigin, addresses[i].ValueNew);
                        }

                        copy = new byte[12];
                        Array.Copy(data, 0, copy, 0, 12);
                        copy[4] = 0x00;
                        copy[5] = 0x06;
                        break;
                    }

                    default:
                    {
                        copy = new byte[9];
                        Array.Copy(data, 0, copy, 0, 8);
                        copy[4] = 0x00;
                        copy[5] = 0x03;
                        copy[7] = (byte)(data[7] + 0x80);
                        copy[8] = 0x01;          // 不支持的功能码
                        break;
                    }
                    }
                }
                catch (Exception ex)
                {
                    state.WorkSocket?.Close( );
                    state = null;
                    LogNet?.WriteException(LogHeaderText, ex);
                    return;
                }



                try
                {
                    // 管他是什么,先开始数据接收
                    // state.WorkSocket?.Close();
                    state.WorkSocket.BeginReceive(state.HeadByte, 0, 6, SocketFlags.None, new AsyncCallback(ModbusHeadReveiveCallback), state);
                }
                catch (Exception ex)
                {
                    state.WorkSocket?.Close();
                    state = null;
                    LogNet?.WriteException(LogHeaderText, "Send exception:", ex);
                    return;
                }


                // 回发数据,先获取发送锁
                state.hybirdLock.Enter();
                state.WorkSocket.BeginSend(copy, 0, size: copy.Length, socketFlags: SocketFlags.None, callback: new AsyncCallback(DataSendCallBack), state: state);


                // 通知处理消息
                if (IsStarted)
                {
                    OnDataReceived?.Invoke(data);
                }
            }
        }
        /// <summary>
        /// 当接收到了新的请求的时候执行的操作
        /// </summary>
        /// <param name="socket">异步对象</param>
        /// <param name="endPoint">终结点</param>
        protected override void ThreadPoolLogin(Socket socket, IPEndPoint endPoint)
        {
            // 注册包
            // 0x48 0x73 0x6E 0x00 0x17 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x31 0x00 0x00 0x00 0x00 0x00 0x00 0xC0 0xA8 0x00 0x01 0x17 0x10
            // +------------+ +--+ +--+ +----------------------------------------------------+ +---------------------------+ +-----------------+ +-------+
            // + 固定消息头  +备用 长度           DTU码 12345678901 (唯一标识)                  登录密码(不受信的排除)     Ip:192.168.0.1    端口10000
            // +------------+ +--+ +--+ +----------------------------------------------------+ +---------------------------+ +-----------------+

            // 返回
            // 0x48 0x73 0x6E 0x00 0x01 0x00
            // +------------+ +--+ +--+ +--+
            //   固定消息头  备用 长度 结果代码

            // 结果代码
            // 0x00: 登录成功
            // 0x01: DTU重复登录
            // 0x02: DTU禁止登录
            // 0x03: 密码验证失败

            OperateResult <byte[]> check = ReceiveByMessage(socket, 5000, new AlienMessage( ));

            if (!check.IsSuccess)
            {
                return;
            }

            if (check.Content[4] != 0x17 || check.Content.Length != 0x1C)
            {
                socket?.Close( );
                LogNet?.WriteWarn(ToString( ), "Length Check Failed");
                return;
            }

            // 密码验证
            bool isPasswrodRight = true;

            for (int i = 0; i < password.Length; i++)
            {
                if (check.Content[16 + i] != password[i])
                {
                    isPasswrodRight = false;
                    break;
                }
            }

            string dtu = Encoding.ASCII.GetString(check.Content, 5, 11).Trim( );

            // 密码失败的情况
            if (!isPasswrodRight)
            {
                OperateResult send = Send(socket, GetResponse(StatusPasswodWrong));
                if (send.IsSuccess)
                {
                    socket?.Close( );
                }
                LogNet?.WriteWarn(ToString( ), "Login Password Wrong, Id:" + dtu);
                return;
            }

            AlienSession session = new AlienSession( )
            {
                DTU    = dtu,
                Socket = socket,
            };

            // 检测是否禁止登录
            if (!IsClientPermission(session))
            {
                OperateResult send = Send(socket, GetResponse(StatusLoginForbidden));
                if (send.IsSuccess)
                {
                    socket?.Close( );
                }
                LogNet?.WriteWarn(ToString( ), "Login Forbidden, Id:" + session.DTU);
                return;
            }

            // 检测是否重复登录,不重复的话,也就是意味着登录成功了
            if (IsClientOnline(session))
            {
                OperateResult send = Send(socket, GetResponse(StatusLoginRepeat));
                if (send.IsSuccess)
                {
                    socket?.Close( );
                }
                LogNet?.WriteWarn(ToString( ), "Login Repeat, Id:" + session.DTU);
                return;
            }
            else
            {
                OperateResult send = Send(socket, GetResponse(StatusOk));
                if (!send.IsSuccess)
                {
                    return;
                }
            }

            // 触发上线消息
            OnClientConnected?.Invoke(this, session);
        }
        private void ModbusHeadReveiveCallback(IAsyncResult ar)
        {
            if (ar.AsyncState is ModBusState state)
            {
                try
                {
                    int receiveCount = state.WorkSocket.EndReceive(ar);
                    if (receiveCount == 0)
                    {
                        state.WorkSocket?.Close( );
                        LogNet?.WriteDebug(ToString( ), $"客户端 [ {state.IpEndPoint} ] 下线");
                        return;
                    }
                    else
                    {
                        state.HeadByteReceivedLength += receiveCount;
                    }
                }
                catch (Exception ex)
                {
                    // 关闭连接,记录日志
                    state.WorkSocket?.Close( );
                    LogNet?.WriteException(ToString(), $"客户端 [ {state.IpEndPoint} ] 异常下线,消息子节接收失败!", ex);
                    return;
                }

                try
                {
                    if (state.HeadByteReceivedLength < state.HeadByte.Length)
                    {
                        // 数据不够,继续接收
                        state.WorkSocket.BeginReceive(state.HeadByte, state.HeadByteReceivedLength, state.HeadByte.Length - state.HeadByteReceivedLength,
                                                      SocketFlags.None, new AsyncCallback(ModbusHeadReveiveCallback), state);
                        return;
                    }
                }
                catch (Exception ex)
                {
                    state.WorkSocket?.Close( );
                    LogNet?.WriteException(ToString( ), $"客户端 [ {state.IpEndPoint} ] 异常下线,再次启动接收失败!", ex);
                    return;
                }


                // 准备接收的数据长度
                int ContentLength = state.HeadByte[4] * 256 + state.HeadByte[5];
                // 第一次过滤,过滤掉不是Modbus Tcp协议的
                if (state.HeadByte[2] == 0x00 &&
                    state.HeadByte[3] == 0x00 &&
                    ContentLength < 300)
                {
                    try
                    {
                        // 头子节接收完成
                        state.Content = new byte[ContentLength];
                        state.ContentReceivedLength = 0;
                        // 开始接收内容
                        state.WorkSocket.BeginReceive(state.Content, state.ContentReceivedLength, state.Content.Length - state.ContentReceivedLength,
                                                      SocketFlags.None, new AsyncCallback(ModbusDataReveiveCallback), state);
                    }
                    catch (Exception ex)
                    {
                        state.WorkSocket?.Close( );
                        LogNet?.WriteException(ToString( ), $"客户端 [ {state.IpEndPoint} ] 异常下线,启动内容接收失败!", ex);
                        return;
                    }
                }
                else
                {
                    // 关闭连接,记录日志
                    state.WorkSocket?.Close( );
                    LogNet?.WriteWarn(ToString(), $"客户端 [ {state.IpEndPoint} ] 下线,不是标准的Modbus协议!");
                }
            }
        }
        private void AsyncCallback(IAsyncResult ar)
        {
            if (ar.AsyncState is AppSession session)
            {
                try
                {
                    int received = session.WorkSocket.EndReceiveFrom(ar, ref session.UdpEndPoint);
                    // 马上开始重新接收,提供性能保障
                    RefreshReceive();
                    session.IpEndPoint = (IPEndPoint)session.UdpEndPoint;

                    int    contentLength      = session.BytesContent[2] * 256 + session.BytesContent[3];
                    byte[] dtuNumArray        = new byte[11];
                    byte[] publicNetworkArray = new byte[4];
                    byte[] publicPortArray    = new byte[2];

                    if (contentLength > 0)
                    {
                        Array.Copy(session.BytesContent, 4, dtuNumArray, 0, 11);
                        Array.Copy(session.BytesContent, 15, publicNetworkArray, 0, 4);
                        Array.Copy(session.BytesContent, 19, publicPortArray, 0, 2);
                    }
                    if (session.BytesContent[0] == 0x7b) // 代表宏电DDP协议
                    {
                        string dtuNum = Encoding.ASCII.GetString(dtuNumArray, 0, 11).Trim();
                        // 解析内容
                        if (session.BytesContent[1] == 0x01 && contentLength == 22)                                                // 0x01 终端请求注册
                        {
                            string publicNetwork = BasicFramework.SoftBasic.ByteToHexTenString(publicNetworkArray, '.');           // 终端内网IP
                            int    publicPort    = Convert.ToInt32(BasicFramework.SoftBasic.ByteToHexString(publicPortArray), 16); //终端内网端口
                            SendBytesAsync(session, BuildDtuNumCommand(dtuNumArray));
                            LogNet?.WriteInfo(ToString(), $"请求注册 终端号码:{dtuNum} 终端公网IP:{session.IpEndPoint} 终端内网IP:{publicNetwork}:{publicPort}");
                        }

                        if (session.BytesContent[1] == 0x02 && contentLength == 16) // 0x02 终端请求注销
                        {
                            LogNet?.WriteInfo(ToString(), $"请求注销 终端号码:{dtuNum}");
                        }

                        if (session.BytesContent[1] == 0x09)                           // 0x09 发送给DSC的用户数据包
                        {
                            byte[] instructArray = new byte[session.BytesContent[18]]; // 接收的指令长度(不包含宏电数据头)
                            Array.Copy(session.BytesContent, 16, instructArray, 0, session.BytesContent[18]);

                            LogNet?.WriteInfo(ToString(), $"发送给DSC的用户数据包 终端号码:{dtuNum} 数据捕获:{BasicFramework.SoftBasic.ByteToHexString(instructArray, ' ')}");
                        }
                    }
                    else
                    {
                        LogNet?.WriteWarn(ToString(), $"数据捕获:{BasicFramework.SoftBasic.ByteToHexString(session.BytesContent, ' ')}");
                    }
                }
                catch (ObjectDisposedException)
                {
                    //主程序退出的时候触发
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException(ToString(), StringResources.Language.SocketEndReceiveException, ex);
                    //重新接收,此处已经排除掉了对象释放的异常
                    RefreshReceive();
                }
                finally
                {
                    //state = null;
                }
            }
        }