Class3.cs 10.9 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Asa.RFID
{
    /// <summary>
    /// 读取所有RFID
    /// </summary>
    public class ReadAll : IReadAll
    {
        ///// <summary>
        ///// 接收数据包事件
        ///// </summary>
        ///// <param name="ip"></param>
        ///// <param name="id"></param>
        //public delegate void ReceivedEvent(string ip, string id);
        ///// <summary>
        ///// 接收数据包
        ///// </summary>
        //public event ReceivedEvent Received;
        ///// <summary>
        ///// 接收网卡缓存事件
        ///// </summary>
        ///// <param name="ip"></param>
        ///// <param name="buffer"></param>
        //public delegate void ReceiveBufferEvent(string ip, byte[] buffer);
        ///// <summary>
        ///// 接收网卡缓存
        ///// </summary>
        //public event ReceiveBufferEvent ReceiveBuffer;



        private bool _loop;
        private Socket _server;         //服务端
        private List<Client> _client;   //所有客户端
        private Thread tListenClient;   //监听客户端连接
        private Dictionary<string, string> _id;  //RFID编号
        private log4net.ILog log = null;
        private const int CLIENT_SLEEP = 10;

        public event IReadAll.ReceivedEvent Received;
        public event IReadAll.ReceiveBufferEvent ReceiveBuffer;



        /// <summary>
        /// 读取所有RFID
        /// </summary>
        /// <param name="logName">日志名称</param>
        public ReadAll(string logName)
        {
            _id = new Dictionary<string, string>();
            if (log == null)
                log = log4net.LogManager.GetLogger(logName);
        }

        /// <summary>
        /// 开启
        /// </summary>
        /// <param name="port">RFID设备的端口</param>
        public void Start(int port = 13000)
        {
            try
            {
                IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
                _server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _server.Bind(localEP);
                _server.Listen(100);

                _loop = true;
                _client = new List<Client>();
                tListenClient = new Thread(new ThreadStart(ListenClient));
                tListenClient.Start();

                log.Info("Server Start");
            }
            catch (Exception ex)
            {
                log.Error("Start", ex);
            }
        }

        public void Start(string[] ip)
        {

        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            _loop = false;
            for (int i = 0; i < _client.Count; i++)
                ClientClose(i);

            try
            {
                _id.Clear();
                _server.Close();
                _client = null;
                log.Info("Server Stop");
            }
            catch (Exception ex)
            {
                log.Error("Stop", ex);
            }
        }

        /// <summary>
        /// 读取ID号
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public string Read(string ip)
        {
            if (_id.TryGetValue(ip, out string value))
            {
                log.Info("Read " + ip + " -> " + value);
                return value;
            }
            else
            {
                log.Info("Read " + ip + " not exist, return 000");
                return "000";
            }
        }

        /// <summary>
        /// 清除缓存
        /// </summary>
        /// <param name="ip"></param>
        public void Clear(string ip)
        {
            if (_id.ContainsKey(ip))
            {
                _id[ip] = "000";
                log.Info("Clear " + ip);
            }
            else
            {
                log.Info("Clear " + ip + " not exist");
            }

        }









        private void ClientClose(int idx)
        {
            try
            {
                _client[idx].Loop = false;
                _client[idx].IsConn = false;
                _client[idx].Socket.Close();
                log.Info(_client[idx].IP + " Close");
            }
            catch (Exception ex)
            {
                log.Error(_client[idx].IP + " ClientClose", ex);
            }
        }

        private void ListenClient()
        {
            while (_loop)
            {
                try
                {
                    Socket socket = _server.Accept();  //这边会暂停,不需要sleep
                    IPEndPoint ep = (IPEndPoint)socket.RemoteEndPoint;
                    Thread listen = new Thread(new ParameterizedThreadStart(ListenNet));
                    string ip = ep.Address.ToString();

                    //新的客户端
                    Client client = new Client
                    {
                        IP = ip,
                        Loop = true,
                        IsConn = true,
                        Socket = socket,
                        ListenNet = listen,
                    };

                    //重连后关闭旧连接
                    int idx = _client.FindIndex(s => s.IP.Equals(ip));
                    if (idx > -1)
                    {
                        _id[_client[idx].IP] = "000";
                        _client[idx].IsConn = false;
                        _client[idx].Loop = false;
                        _client[idx].Socket.Close();
                        log.Info(_client[idx].IP + " 重连,删除重复。");
                        _client.RemoveAt(idx);
                    }

                    //添加到数组
                    if (!_id.ContainsKey(client.IP))
                        _id.Add(client.IP, "000");
                    _client.Add(client);
                    log.Info(client.IP + " 连接");
                    listen.Start(_client.Count - 1);
                }
                catch (SocketException)
                {
                    //关闭连接,退出阻塞Accept
                    log.Error("Socket Close");
                }
                catch (Exception ex)
                {
                    log.Error("ListenClient", ex);
                }
            }
        }

        private void ListenNet(object obj)
        {
            const int LENGTH = 8;  //实际使用8字节
            Client client = _client[(int)obj];
            List<byte> receive = new List<byte>();
            byte[] buff = new byte[client.Socket.ReceiveBufferSize];

            while (client.Loop)
            {
                Thread.Sleep(CLIENT_SLEEP);
                try
                {
                    if (!client.Loop) break;
                    if (client.Socket.Available > 0)
                    {
                        int count = client.Socket.Receive(buff);
                        byte[] temp = new byte[count];
                        Array.Copy(buff, 0, temp, 0, count);

                        //16进制字符串转字节数组
                        string s = Encoding.ASCII.GetString(temp);
                        s = s.Replace("\r", "");
                        s = s.Replace("\n", "");
                        log.Debug("ListenNet " + s);
                        temp = new byte[s.Length / 2];
                        for (int i = 0; i < temp.Length; i++)
                        {
                            temp[i] = Convert.ToByte(s.Substring(i * 2, 2), 16);
                        }

                        receive.AddRange(temp);
                        log.Debug("Receive[" + client.IP + "]: " + HexBuff(temp));
                        //Task.Run(() => ReceiveBuffer?.Invoke(client.IP, temp));

                        do
                        {
                            //查找包头
                            int idx = receive.FindIndex(n => n == 0x5A);
                            if (idx == -1)
                            {
                                log.Debug("清除缓存[" + client.IP + "]: " + HexBuff(receive));
                                receive.Clear();
                                break;
                            }

                            //长度不够,半个包
                            int len = idx + LENGTH;
                            if (len > receive.Count) break;

                            //查找包尾
                            if (receive[len - 3] == 0x4A)  //一个系统的0,两个校验位
                            {
                                byte[] arr = new byte[LENGTH];
                                receive.CopyTo(idx, arr, 0, 4);
                                receive.CopyTo(idx + 4, arr, 4, 4);
                                log.Info("Packet[" + client.IP + "]: " + HexBuff(arr));

                                TriggerEvent(client.IP, arr);

                                //2020年6月5日
                                //Task.Run(() => TriggerEvent(client.IP, arr));

                            }
                            else
                            {
                                log.Debug("没有包尾[" + client.IP + "]: " + HexBuff(receive));
                            }
                            receive.RemoveRange(0, len);
                        } while (true);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(client.IP + " ListenNet", ex);
                }

            }
        }

        private void TriggerEvent(string ip, byte[] buff)
        {
            string s;
            if (buff[1] == 0)
            {
                s = "000";
                log.Info(ip + " byte 0");
            }
            else
            {
                s = (char)buff[1] + buff[2].ToString();
            }

            //添加到缓存
            if (_id[ip].Equals(s))
            {
                log.Debug("相同ID[" + ip + "]: " + s);
            }
            else
            {
                _id[ip] = s;
                log.Info("Trigger[" + ip + "]: " + s);
                Task.Run(() => Received?.Invoke(ip, s));
            }

        }

        private string HexBuff(byte[] buff)
        {
            string s = "";
            if (buff == null) return s;

            for (int i = 0; i < buff.Length; i++)
                s += buff[i].ToString("X2") + " ";
            return s;
        }

        private string HexBuff(List<byte> buff)
        {
            string s = "";
            if (buff == null) return s;

            for (int i = 0; i < buff.Count; i++)
                s += buff[i].ToString("X2") + " ";
            return s;
        }

        private class Client
        {
            public bool Loop;
            public string IP;
            public bool IsConn;
            public Socket Socket;
            public Thread ListenNet;

        }

    }
}