科星互联RFID网络读卡器 for C#

一、产品外观

        因为项目中需要使用网络接口ETHICR IC读卡器,公司购买了科星互联产品,外观如下:

        

二、开发前设置

        使用产品提供的开发工具,可以对读卡器进行配置,其中最主要的就是两点:

        1、IP地址配置:

                本地IP为读卡器的IP地址:192.168.1.230

                子网掩码:255.255.255.0

                网关地址为网络中路由器的IP地址:192.168.1.1

                远程IP为工作模式使用TCP客户端时使用:192.168.1.251

                端品号为工作模式使用TCP时使用:50000

                数据监测:0Min(不用修改)

        2、工作模式配置:

                TCP服务器:

                使用此模式时,上位机必须连接到上面设置的IP地址及端口号,如果有读卡时,将实时通过TCP传送卡号。

                使用此模式前,必须创建 Socket连接。

                TCP客户端:(我是使用此模式,这样节约资源,方便管理,如果存在多个读卡器时)

                此模式与TCP服务器模式差不多,差别就是创建 Socket连接时,读卡器连接到上位机。

                使用此模式前,必须创建 Socket连接。

                其他暂不用就不多说了。

  配置软件界面如下:               

三、C#开发

        1、创建读卡器类 Reader:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace NetReader
{
    public class Reader
    {

        public int Port { get; set; }
        public bool Reading { get; set; }     //读卡器读与设置状态
        public bool IsOpen { get; set; }     //端口连接状态
        public int Index { get; set; }

        public int ReaderType { get; set; }  //读卡器类型,3=二维码,4=科星互联网口读卡器
        
        private Socket socketSend;      //负责发送信息的socket
        private Socket socketWatch;     //监听socket

        //将远程连接的客户端的IP地址和Socket存入集合中  
        private Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();

        public delegate void QRCodeReaderDataReceive(int index, string cardId);
        public event QRCodeReaderDataReceive dataReceive;

        public delegate void QRCodeReaderStatus(int index, string status);
        public event QRCodeReaderStatus readerStatus;

        //缺省9999端口
        public Server(int _index, int _port = 9999)
        {
            Index = _index;
            Port = _port;
        }

        /* 
         * 开启监听
         */
        public void StartMonitor()
        {
            try
            {
                //当点击开始监听的时候 在服务器端创建一个负责监听IP地址和端口号的Socket  
                //addressFamily: Socket:使用的寻址方案,socketType:Socket 的类型,protocolType:Socket 使用的协议。           
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Any;
                //创建服务器端网络端点对象  
                IPEndPoint point = new IPEndPoint(ip, Port);
                //侦听Soket与本地终结点绑定  
                socketWatch.Bind(point);
                //设置为监听状态  
                socketWatch.Listen(10);                
                readerStatus?.Invoke(Index, String.Format("{1} 服务在端口:{0} 监听成功!" , Port, GetReaderTypeName()));
                //新建线程等待连接,创建通信Socket  
                Thread th = new Thread(Listen);
                th.IsBackground = true;//设置为后台线程  
                th.Start(socketWatch);
                IsOpen = true;
            }
            catch(Exception ex)
            {
                readerStatus?.Invoke(Index, string.Format("启动监听 {0} 失败:{1}", GetReaderTypeName(), ex.Message)); 
                IsOpen = false;
            }
        }

        private string GetReaderTypeName()
        {
            return ReaderType == 3 ? "二维码读卡器" : "网口读卡器";
        }

        /* 
         * 监听服务
         */
        private void Listen(object o)
        {
            Socket sWatch = o as Socket;
            //循环目的在于使得多个客户端可以连接服务器  
            while (Reading)
            {
                try
                {
                    //等待客户端连接,由侦听的Socket创建一个负责与客户端通信的Socket  
                    socketSend = sWatch.Accept();
                    //将远程连接的客户端的IP地址和Socket存入集合中  
                    dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
                    //将远程连接的客户端的IP地址和端口号存入下拉框中  
                    readerStatus?.Invoke(Index, socketSend.RemoteEndPoint.ToString() + ":" + string.Format(" {0} 连接成功", GetReaderTypeName()));    //获得远程的客户端的IP地址和端口号  
                    //创建新线程不停的接受客户端发过来的消息  
                    Thread th = new Thread(Receive);
                    th.IsBackground = true;
                    th.Start(socketSend);
                }
                catch(Exception ex)
                {
                    readerStatus?.Invoke(Index, string.Format("监听 {0} 失败:{1}", GetReaderTypeName(), ex.Message));
                }
            }
        }

        /// <summary>  
        /// 服务器端不停的接受客户端发来的消息  
        /// </summary>  
        /// <param name="o"></param>  
        private void Receive(object o)
        {
            Socket sSend = o as Socket;
            while (Reading)
            {
                if (sSend.Connected)
                {
                    try
                    {
                        //客户端连接成功后接受客户端发来的消息  
                        byte[] buf = new byte[1024 * 1024 * 2];
                        int r = sSend.Receive(buf);                  //实际接受的字节数                                                                       
                        string data = "";
                        if (r == 0)                                  //如果客户端关闭,发送的有效字节数为0  
                        {
                            readerStatus?.Invoke(Index, string.Format("接收 {0} 数据长度为零,终止连接。", GetReaderTypeName()));
                            IsOpen = false;
                            break;
                        }
                        else
                        {
                            byte[] recData = new byte[r];
                            Array.Copy(buf, 0, recData, 0, r); //5A AA
                            switch (r)
                            {
                                case 6:    //QRcode connected.
                                    data = Encoding.UTF8.GetString(buf, 0, r);
                                    if (data.Equals("dragon"))
                                    {
                                        Debug.Print("only receive heardbeat information, don't send heardbeat");                                        
                                    }                                    
                                    break;
                                case 7:    //Network interface reader connected.  
                                    if (recData[0] == 0x55 && recData[1] == 0xAA)   //heardbeat
                                    {                                        
                                        try
                                        {
                                            if (dicSocket.Count > 0)
                                            {
                                                dicSocket[sSend.RemoteEndPoint.ToString()].Send(recData);
                                            }
                                        }
                                        catch
                                        {

                                        }
                                    }                                    
                                    break;
                                default:
                                    switch (ReaderType)
                                    {
                                        case 3:
                                            data = Encoding.UTF8.GetString(buf, 0, r);
                                            string id = getCardId(data);
                                            if (!id.Equals(""))
                                            {
                                                //QRcode include 'code=0000' flag.
                                                byte[] bufSend = Encoding.UTF8.GetBytes("code=0000");
                                                try
                                                {
                                                    if (dicSocket.Count > 0)
                                                    {
                                                        //Notify device receive success.
                                                        dicSocket[sSend.RemoteEndPoint.ToString()].Send(bufSend);
                                                    }
                                                    Debug.Print("Scan data:" + id);
                                                    dataReceive?.Invoke(Index, id);
                                                }
                                                catch
                                                {

                                                }
                                            }                                        
                                            break;
                                        case 4:
                                            if (r > 5)  // && r == 10
                                            {
                                                try
                                                {
                                                    //byte[] cardId = new byte[recData.Length - 5];
                                                    //Array.Copy(recData, 5, cardId, 0, recData.Length - 5);
                                                    //string ids = byteToHexStr(recData, recData.Length);
                                                    string ids = Encoding.ASCII.GetString(recData);
                                                    Debug.Print(ids);
                                                    dataReceive?.Invoke(Index, ids);
                                                }
                                                catch
                                                {

                                                }
                                            }
                                            break;
                                    }
                                    break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        readerStatus?.Invoke(Index, string.Format("接收 {0} 数据发生错误:{1}", GetReaderTypeName(), ex.Message));
                        IsOpen = false;
                        break;
                    }
                }
                else
                {
                    readerStatus?.Invoke(Index, string.Format("接收 {0} 数据发生错误:连接断开!", GetReaderTypeName()));
                    IsOpen = false;
                    break;
                }                
            }

        }

        /**
         *  给出当前卡号
         *  vgdecoderesult=1333470964&&devicenumber=1&&otherparams=
         */
        private string getCardId(string raw)
        {
            if (raw.Length > 17)
            {
                int start = raw.IndexOf("vgdecoderesult=");
                int end = raw.IndexOf("&&", start);
                try
                {
                    return raw.Substring(start + 15, end - start - 15);
                }
                catch (Exception)
                {
                    return "";
                }
            }
            else
            {
                return "";
            }
        }


        /* 
         * 关闭监听服务
         */
        public void Close()
        {
            try
            {
                IsOpen = false;
                Reading = false;
                if (socketWatch != null)
                {
                    if (socketWatch.Connected) socketWatch.Disconnect(true);
                    socketWatch.Close();
                    socketWatch.Dispose();
                }
                if (dicSocket.Count > 0)
                {
                    dicSocket.Remove(socketSend.RemoteEndPoint.ToString());
                }
                if (socketSend != null)
                {
                    if (socketSend.Connected) socketSend.Disconnect(true);
                    socketSend.Close();
                    socketSend.Dispose();                    
                }                    
            }
            catch (Exception ex)
            {
                readerStatus?.Invoke(Index, "关闭QRCode监听服务发生错误:" + ex.Message);
            }
        }

        /**
          * 字符串转16进制
          */
        public byte[] HexStringToByteArray(string s)
        {
            try
            {
                s = s.Replace(" ", "");
                byte[] buffer = new byte[s.Length / 2];
                for (int i = 0; i < s.Length; i += 2)
                    buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
                return buffer;
            }
            catch (Exception)
            {               
                return null;
            }
        }
        //字节数组转16进制字符串
        private static string byteToHexStr(byte[] bytes, int length)
        {
            try
            {
                string returnStr = "";
                if (bytes != null)
                {
                    for (int i = 0; i < length; i++)
                    {
                        returnStr += bytes[i].ToString("X2");
                    }
                }
                return returnStr;
            }
            catch (Exception)
            {
                return "";
            }
        }
    }
}

        2、获取卡号问题:(上面代码可以正常获取卡号)

        使用Receive获取卡号方法中,如果使用 byte转hex字符串时,与开发工具中读卡的卡号不一样。

//与读卡器获取的卡号不一致
string ids = byteToHexStr(recData, recData.Length);

        读卡器卡号是通过 byte转string方式

//此方法与开发工具获取的卡号一致
string ids = Encoding.ASCII.GetString(recData);

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值