Class1.cs 6.3 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
{
    public class ReadAll
    {
        public delegate void ReceivedEvent(string ip, string id);
        public event ReceivedEvent Received;
        public delegate void ReceiveBufferEvent(string ip, byte[] buffer);
        public event ReceiveBufferEvent ReceiveBuffer;
        public delegate void LogEvent(string ip, string log);
        public event LogEvent Log;

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

        public ReadAll()
        {
            _id = new Dictionary<string, string>();
        }

        public void Start(int port = 13000)
        {
            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();
        }

        public void Stop()
        {
            _loop = false;
            for (int i = 0; i < _client.Count; i++)
            {
                _client[i].Loop = false;
                _client[i].IsConn = false;
                _client[i].Socket.Close();
            }
            _id.Clear();
            _server.Close();
            _client = null;
        }

        public string Read(string ip)
        {
            if (_id.TryGetValue(ip, out string value))
                return value;
            else
                return "000";
        }

        public void Clear(string ip)
        {
            _id[ip] = "000";
        }

        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?.Invoke(_client[idx].IP, "offline");
                        _client.RemoveAt(idx);
                    }

                    //添加到数组
                    if (!_id.ContainsKey(client.IP))
                        _id.Add(client.IP, "000");
                    _client.Add(client);
                    Log?.Invoke(client.IP, "online");
                    listen.Start(_client.Count - 1);
                }
                catch (SocketException)
                {
                    //关闭连接,退出阻塞Accept
                }
                catch (Exception 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);
                        receive.AddRange(temp);
                        Task.Run(() => ReceiveBuffer?.Invoke(client.IP, temp));

                        int idx = receive.FindIndex(n => n == 0x5A);
                        if (idx == -1)
                        {
                            receive.Clear();
                            continue;
                        }

                        int len = idx + LENGTH + 1;  //一个系统自带的0
                        if (len > receive.Count)
                            continue;

                        if (receive[len - 3] == 0x4A)  //一个系统的0,两个校验位
                        {
                            byte[] arr = new byte[LENGTH];
                            receive.CopyTo(idx, arr, 0, 4);
                            receive.CopyTo(idx + 5, arr, 4, 4);
                            Task.Run(() => TriggerEvent(client.IP, arr));
                        }
                        receive.RemoveRange(0, len);
                    }
                }
                catch (Exception ex)
                {
                    //client.Loop = false;
                }

            }
        }

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

            if (!_id[ip].Equals(s))
            {
                _id[ip] = s;
                Log?.Invoke(ip, s);
                Received?.Invoke(ip, s);
            }
        }

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



    }
}