ClassDeviceNet.cs 5.19 KB
using HslCommunication.Core;
using HslCommunication.Core.Net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace HslCommunication.Enthernet
{

    /// <summary>
    /// 通用设备的基础网络信息
    /// </summary>
    public class DeviceNet : NetworkServerBase
    {

        #region Constructor

        /// <summary>
        /// 实例化一个通用的设备类
        /// </summary>
        public DeviceNet()
        {
            list = new List<DeviceState>();
            lock_list = new SimpleHybirdLock();
        }

        #endregion

        #region Connection Management


        private List<DeviceState> list;                // 所有客户端的连接对象
        private SimpleHybirdLock lock_list;            // 列表锁

        private void AddClient(DeviceState device)
        {
            lock_list.Enter();
            list.Add(device);
            lock_list.Leave();

            ClientOnline?.Invoke(device);
        }

        private void RemoveClient(DeviceState device)
        {
            lock_list.Enter();
            list.Remove(device);
            device.WorkSocket?.Close();
            lock_list.Leave();

            ClientOffline?.Invoke(device);
        }


        #endregion

        #region Event Handle


        /// <summary>
        /// 当客户端上线的时候,触发此事件
        /// </summary>
        public event Action<DeviceState> ClientOnline;

        /// <summary>
        /// 当客户端下线的时候,触发此事件
        /// </summary>
        public event Action<DeviceState> ClientOffline;


        /// <summary>
        /// 按照ASCII文本的方式进行触发接收的数据
        /// </summary>
        public event Action<DeviceState, string> AcceptString;

        /// <summary>
        /// 按照字节的方式进行触发接收的数据
        /// </summary>
        public event Action<DeviceState, byte[]> AcceptBytes;

        #endregion

        #region Private Member

        private readonly byte endByte = 0x0D;                   // 结束的指令


        #endregion

        /// <summary>
        /// 当接收到了新的请求的时候执行的操作
        /// </summary>
        /// <param name="socket">异步对象</param>
        /// <param name="endPoint">终结点</param>
        protected override void ThreadPoolLogin(Socket socket, IPEndPoint endPoint)
        {
            // 登录成功
            DeviceState stateone = new DeviceState()
            {
                WorkSocket = socket,
                DeviceEndPoint = (IPEndPoint)socket.RemoteEndPoint,
                IpAddress = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString(),
                ConnectTime = DateTime.Now,
            };

            AddClient(stateone);

            try
            {
                stateone.WorkSocket.BeginReceive(stateone.Buffer, 0, stateone.Buffer.Length, SocketFlags.None,
                    new AsyncCallback(ContentReceiveCallBack), stateone);
            }
            catch (Exception ex)
            {
                //登录前已经出错
                RemoveClient(stateone);
                LogNet?.WriteException(ToString(), StringResources.Language.NetClientLoginFailed, ex);
            }
        }


        private void ContentReceiveCallBack(IAsyncResult ar)
        {
            if (ar.AsyncState is DeviceState stateone)
            {
                try
                {
                    int count = stateone.WorkSocket.EndReceive(ar);

                    if (count > 0)
                    {
                        MemoryStream ms = new MemoryStream();
                        byte next = stateone.Buffer[0];

                        while (next != endByte)
                        {
                            ms.WriteByte(next);
                            byte[] buffer = new byte[1];
                            stateone.WorkSocket.Receive(buffer, 0, 1, SocketFlags.None);
                            next = buffer[0];
                        }

                        // 接收完成
                        stateone.WorkSocket.BeginReceive(stateone.Buffer, 0, stateone.Buffer.Length, SocketFlags.None,
                            new AsyncCallback(ContentReceiveCallBack), stateone);


                        byte[] receive = ms.ToArray();
                        ms.Dispose();

                        lock_list.Enter();
                        stateone.ReceiveTime = DateTime.Now;
                        lock_list.Leave();
                        AcceptBytes?.Invoke(stateone, receive);
                        AcceptString?.Invoke(stateone, Encoding.ASCII.GetString(receive));
                    }
                    else
                    {
                        RemoveClient(stateone);
                        LogNet?.WriteInfo(ToString(), StringResources.Language.NetClientOffline);
                    }
                }
                catch (Exception ex)
                {
                    //登录前已经出错
                    RemoveClient(stateone);
                    LogNet?.WriteException(ToString(), StringResources.Language.NetClientLoginFailed, ex);
                }
            }
        }

    }


}