zoukankan      html  css  js  c++  java
  • .net 4.0以下版本实现web socket服务

    直接上代码:

    1. WebSocket.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Net.Sockets;
    using System.Net;
    using System.Text.RegularExpressions;
    using System.Security.Cryptography;
    using System.Reflection;
    
    namespace BH.WebSocketServer
    {
        public class WebSocket
        {
            log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
            private Dictionary<string, Session> SessionPool = new Dictionary<string, Session>();
            private Dictionary<string, string> MsgPool = new Dictionary<string, string>();
            private Socket _socket=null;
            public Socket SockeServer
            {
                get
                {
                    return this._socket;
                }
            }
    
    
            #region 启动WebSocket服务
            /// <summary>
            /// 启动WebSocket服务
            /// </summary>
            public void start(int port)
            {
                this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                SockeServer.Bind(new IPEndPoint(IPAddress.Any, port));
                SockeServer.Listen(20);
                SockeServer.BeginAccept(new AsyncCallback(Accept), SockeServer);
                log.Info("Socket服务已启动,PORT:"+port);
                Console.WriteLine("服务已启动");
                Console.WriteLine("按任意键关闭服务");
    
                while (true)
                {
                    Thread.Sleep(20 * 1000);
                }
                //this._socket = null;
                log.Info("Socket服务已停止");
    
            }
            #endregion
    
            #region 处理客户端连接请求
            /// <summary>
            /// 处理客户端连接请求
            /// </summary>
            /// <param name="result"></param>
            private void Accept(IAsyncResult socket)
            {
                // 还原传入的原始套接字
                Socket SockeServer = (Socket)socket.AsyncState;
                // 在原始套接字上调用EndAccept方法,返回新的套接字
                Socket SockeClient = SockeServer.EndAccept(socket);
                byte[] buffer = new byte[4096];
                try
                {
                    //接收客户端的数据
                    SockeClient.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Recieve), SockeClient);
                    //保存登录的客户端
                    Session session = new Session();
                    session.SockeClient = SockeClient;
                    session.IP = SockeClient.RemoteEndPoint.ToString();
                    session.buffer = buffer;
                    lock (SessionPool)
                    {
                        if (SessionPool.ContainsKey(session.IP))
                        {
                            this.SessionPool.Remove(session.IP);
                        }
                        this.SessionPool.Add(session.IP, session);
                    }
                    //准备接受下一个客户端
                    SockeServer.BeginAccept(new AsyncCallback(Accept), SockeServer);
                    Console.WriteLine(string.Format("Client {0} connected", SockeClient.RemoteEndPoint));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error : " + ex.ToString());
                }
            }
            #endregion
    
            public delegate void EventRecieveData(string msg,Socket sockeClient);
            public event EventRecieveData onRecievData;
    
            #region 处理接收的数据
            /// <summary>
            /// 处理接受的数据
            /// </summary>
            /// <param name="socket"></param>
            private void Recieve(IAsyncResult socket)
            {
                Socket SockeClient = (Socket)socket.AsyncState;
                string IP = SockeClient.RemoteEndPoint.ToString();
                if (SockeClient == null || !SessionPool.ContainsKey(IP))
                {
                    return;
                }
                try
                {
                    int length = SockeClient.EndReceive(socket);
                    byte[] buffer = SessionPool[IP].buffer;
                    SockeClient.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Recieve), SockeClient);
                    string msg = Encoding.UTF8.GetString(buffer, 0, length);
                    //  websocket建立连接的时候,除了TCP连接的三次握手,websocket协议中客户端与服务器想建立连接需要一次额外的握手动作
                    if (msg.Contains("Sec-WebSocket-Key"))
                    {
                        SockeClient.Send(PackageHandShakeData(buffer, length));
                        SessionPool[IP].isWeb = true;
                        return;
                    }
                    if (SessionPool[IP].isWeb)
                    {
                        msg = AnalyzeClientData(buffer, length);
                    }
                    //byte[] msgBuffer = PackageServerData(msg);
                    //foreach (Session se in SessionPool.Values)
                    //{
                    //    //se.SockeClient.Send(msgBuffer, msgBuffer.Length, SocketFlags.None);
                    //}
    
                    if (this.onRecievData!=null)
                    {
                        onRecievData(msg,SockeClient);
    
                    }
                    //add by mo  这里的msg就是客户端发过来的消息。要处理就这里写逻辑代码。
                }
                catch
                {
                    try
                    {
                        SockeClient.Disconnect(true);
                        Console.WriteLine("客户端 {0} 断开连接", IP);
                        SessionPool.Remove(IP);
    
                    }
                    catch (System.Exception ex)
                    {
                    	
                    }
    
                }
            }
            #endregion
    
            #region 客户端和服务端的响应
            /*
             * 客户端向服务器发送请求
             * 
             * GET / HTTP/1.1
             * Origin: http://localhost:1416
             * Sec-WebSocket-Key: vDyPp55hT1PphRU5OAe2Wg==
             * Connection: Upgrade
             * Upgrade: Websocket
             *Sec-WebSocket-Version: 13
             * User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
             * Host: localhost:8064
             * DNT: 1
             * Cache-Control: no-cache
             * Cookie: DTRememberName=admin
             * 
             * 服务器给出响应
             * 
             * HTTP/1.1 101 Switching Protocols
             * Upgrade: websocket
             * Connection: Upgrade
             * Sec-WebSocket-Accept: xsOSgr30aKL2GNZKNHKmeT1qYjA=
             * 
             * 在请求中的“Sec-WebSocket-Key”是随机的,服务器端会用这些数据来构造出一个SHA-1的信息摘要。把“Sec-WebSocket-Key”加上一个魔幻字符串
             * “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用 SHA-1 加密,之后进行 BASE-64编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端
             */
            #endregion
    
            #region 打包请求连接数据
            /// <summary>
            /// 打包请求连接数据
            /// </summary>
            /// <param name="handShakeBytes"></param>
            /// <param name="length"></param>
            /// <returns></returns>
            private byte[] PackageHandShakeData(byte[] handShakeBytes, int length)
            {
                string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, length);
                string key = string.Empty;
                Regex reg = new Regex(@"Sec-WebSocket-Key:(.*?)
    ");
                Match m = reg.Match(handShakeText);
                if (m.Value != "")
                {
                    key = Regex.Replace(m.Value, @"Sec-WebSocket-Key:(.*?)
    ", "$1").Trim();
                }
                byte[] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
                string secKey = Convert.ToBase64String(secKeyBytes);
                var responseBuilder = new StringBuilder();
                responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + "
    ");
                responseBuilder.Append("Upgrade: websocket" + "
    ");
                responseBuilder.Append("Connection: Upgrade" + "
    ");
                responseBuilder.Append("Sec-WebSocket-Accept: " + secKey + "
    
    ");
                return Encoding.UTF8.GetBytes(responseBuilder.ToString());
            }
            #endregion
    
            #region 处理接收的数据
            /// <summary>
            /// 处理接收的数据
            /// 参考 http://www.cnblogs.com/smark/archive/2012/11/26/2789812.html
            /// </summary>
            /// <param name="recBytes"></param>
            /// <param name="length"></param>
            /// <returns></returns>
            private string AnalyzeClientData(byte[] recBytes, int length)
            {
                int start = 0;
                // 如果有数据则至少包括3位
                if (length < 2) return "";
                // 判断是否为结束针
                bool IsEof = (recBytes[start] >> 7) > 0;
                // 暂不处理超过一帧的数据
                if (!IsEof) return "";
                start++;
                // 是否包含掩码
                bool hasMask = (recBytes[start] >> 7) > 0;
                // 不包含掩码的暂不处理
                if (!hasMask) return "";
                // 获取数据长度
                UInt64 mPackageLength = (UInt64)recBytes[start] & 0x7F;
                start++;
                // 存储4位掩码值
                byte[] Masking_key = new byte[4];
                // 存储数据
                byte[] mDataPackage;
                if (mPackageLength == 126)
                {
                    // 等于126 随后的两个字节16位表示数据长度
                    mPackageLength = (UInt64)(recBytes[start] << 8 | recBytes[start + 1]);
                    start += 2;
                }
                if (mPackageLength == 127)
                {
                    // 等于127 随后的八个字节64位表示数据长度
                    mPackageLength = (UInt64)(recBytes[start] << (8 * 7) | recBytes[start] << (8 * 6) | recBytes[start] << (8 * 5) | recBytes[start] << (8 * 4) | recBytes[start] << (8 * 3) | recBytes[start] << (8 * 2) | recBytes[start] << 8 | recBytes[start + 1]);
                    start += 8;
                }
                mDataPackage = new byte[mPackageLength];
                for (UInt64 i = 0; i < mPackageLength; i++)
                {
                    mDataPackage[i] = recBytes[i + (UInt64)start + 4];
                }
                Buffer.BlockCopy(recBytes, start, Masking_key, 0, 4);
                for (UInt64 i = 0; i < mPackageLength; i++)
                {
                    mDataPackage[i] = (byte)(mDataPackage[i] ^ Masking_key[i % 4]);
                }
                return Encoding.UTF8.GetString(mDataPackage);
            }
            #endregion
    
            #region 发送数据
            /// <summary>
            /// 把发送给客户端消息打包处理(拼接上谁什么时候发的什么消息)
            /// </summary>
            /// <returns>The data.</returns>
            /// <param name="message">Message.</param>
            public static byte[] PackageServerData(string msg)
            {
                byte[] content = null;
                byte[] temp = Encoding.UTF8.GetBytes(msg);
                if (temp.Length < 126)
                {
                    content = new byte[temp.Length + 2];
                    content[0] = 0x81;
                    content[1] = (byte)temp.Length;
                    Buffer.BlockCopy(temp, 0, content, 2, temp.Length);
                }
                else if (temp.Length < 0xFFFF)
                {
                    content = new byte[temp.Length + 4];
                    content[0] = 0x81;
                    content[1] = 126;
                    content[2] = (byte)(temp.Length >> 8);
                    content[3] = (byte)(temp.Length & 0xFF);
                    Array.Copy(temp, 0, content, 4, temp.Length);
                }
                else
                {
                    content = new byte[temp.Length + 10];
                    content[0] = 0x81;
                    content[1] = 127;
                    content[2] = 0;
                    content[3] = 0;
                    content[4] = 0;
                    content[5] = 0;
                    content[6] = (byte)(temp.Length >> 24);
                    content[7] = (byte)(temp.Length >> 16);
                    content[8] = (byte)(temp.Length >> 8);
                    content[9] = (byte)(temp.Length & 0xFF);
                    Array.Copy(temp, 0, content, 10, temp.Length);
                }
                return content;
            }
            #endregion
        }
    }
    

    2. Session.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    
    namespace BH.WebSocketServer
    {
        public class Session
        {
            private Socket _sockeclient;
            private byte[] _buffer;
            private string _ip;
            private bool _isweb = false;
    
            public Socket SockeClient
            {
                set { _sockeclient = value; }
                get { return _sockeclient; }
            }
    
            public byte[] buffer
            {
                set { _buffer = value; }
                get { return _buffer; }
            }
    
            public string IP
            {
                set { _ip = value; }
                get { return _ip; }
            }
    
            public bool isWeb
            {
                set { _isweb = value; }
                get { return _isweb; }
            }
        }
    }
    
    

    4. 使用方法

    WebSockete服务器类库:
    使用的时候,绑定事件,EventRecieveData处理客户端发来的消息。
    `           WebSocket socket = new WebSocket();
                socket.onRecievData += new WebSocket.EventRecieveData(socket_onRecievData);
                socket.start(要监听的端口号);
    
    			void socket_onRecievData(string msg, System.Net.Sockets.Socket sockeClient)
    			msg就是收到的消息。
    			sockeClient是发来消息的客户
    
    
    

    5.使用例子:

    以下代码,做成服务,监听指定端口

            private void socket_onRecievData(string msg, System.Net.Sockets.Socket sockeClient)
            {
                SendData sd = new SendData();
                //下面的按真实情况返回。这里只是测试
                BH.JsonHelp.SqlResult result = new BH.JsonHelp.SqlResult()
                {
                    result = false,
                    data = "",
                    errorMessage = ""
                };
                sd.data = result;
                try
                {
    
                    string recvMsg = msg;
                    RecieveData rd = null;
                    try
                    {
                       rd= BH.JsonHelp.JsonHelper.DeserializeJsonToObject<RecieveData>(msg);
                    }
                    catch (System.Exception ex)
                    {
                        LogOuts.Info("msg:" + msg);
                    }
                    if (rd == null)
                    {
                        throw new Exception("收到数据格式不对:"+msg);
                    }
                    int funcId = rd.functionId;
                    string recvData = rd.data;
    
                    //读取到的所有EPC标签
                    List<string> listRecv = new List<string>();
                    string errMsg = string.Empty;
                    //回写给客户端
                    sd.functionId = rd.functionId;
                    switch (rd.functionId)
                    {
                        case 1:
                            //读卡的逻辑
                            result.result = GetEPCInventory(out listRecv, out errMsg);
    
                            if (result.result)
                            {
                                if (listRecv.Count != 1)
                                {
                                    if (listRecv.Count > 1)
                                    {
                                        result.result = false;
                                        result.errorMessage = "读卡器读取的标签超过一张";
                                    }
                                    else if (listRecv.Count == 0)
                                    {
                                        result.result = false;
                                        result.errorMessage = "读卡器附近没有标签可操作";
                                    }
                                }
                                else
                                {
                                    string cardData = "";
    
    
                                    //以下代码读数据是OK的。
                                    //循环读取确保能读到数据
                                    for (int i = 0; i < 10; i++)
                                    {
                                        result.result = ReadEPCTag(listRecv[0], out cardData, out errMsg);
                                        if (result.result)
                                        {
                                            result.data = cardData;
                                            result.errorMessage = listRecv[0];
                                        }
                                        else
                                        {
                                            result.result = false;
                                            result.errorMessage = errMsg;
                                        }
                                        if (cardData != "")
                                        {
                                            break;
                                        }
                                    }
                                    //end   
    
    
                                    /*result.result = ReadEPCTag(listRecv[0], out cardData, out errMsg);
                                    if (result.result)
                                    {
                                        result.errorMessage = listRecv[0];
                                        result.data = cardData;
                                    }
                                    else
                                    {
                                        result.result = false;
                                        result.errorMessage = errMsg;
                                    }*/
                                }
                            }
                            else
                            {
                                result.errorMessage = errMsg;
                            }
    
                            break;
                        case 2:
                            //写卡的逻辑。
                            result.result = GetEPCInventory(out listRecv, out errMsg);
                            if (result.result)
                            {
                                if (listRecv.Count != 1)
                                {
                                    if (listRecv.Count > 1)
                                    {
                                        result.result = false;
                                        result.errorMessage = "读卡器读取的标签超过一张";
                                    }
                                    else if (listRecv.Count == 0)
                                    {
                                        result.result = false;
                                        result.errorMessage = "读卡器附近没有标签可操作";
                                    }
                                }
                                else
                                {
                                    if (string.IsNullOrEmpty(recvData))
                                    {
                                        result.result = false;
                                        result.errorMessage = "标签写入内容不能为空,请输入一些内容!";
                                    }
                                    else
                                    {
                                        recvData = recvData.Replace(" ", "").Replace("
    ", "");
    
                                        //加循环确保写入成功
                                        for (int i = 0; i < 10; i++)
                                        {
                                            result.result = WriteEPCTag(listRecv[0], recvData, out errMsg);
                                            if (result.result)
                                            {
                                                result.data = listRecv[0];
                                                result.errorMessage = listRecv[0];
                                                break;
                                            }
                                            else
                                            {
                                                result.result = false;
                                                result.errorMessage = errMsg;
                                            }
                                        }
    
                                        /*result.result = WriteEPCTag(listRecv[0], recvData, out errMsg);
                                        if (result.result)
                                        {
                                            result.data = listRecv[0];
                                            result.errorMessage = "标签写入成功!";
                                        }
                                        else
                                        {
                                            result.result = false;
                                            result.errorMessage = errMsg;
                                        }*/
                                    }
                                }
                            }
                            else
                            {
                                result.errorMessage = errMsg;
                            }
    
                            break;
                        case 3:
                            //获取标签ID
                            result.result = GetEPCInventory(out listRecv, out errMsg);
    
                            if (result.result)
                            {
                                if (listRecv.Count != 1)
                                {
                                    if (listRecv.Count > 1)
                                    {
                                        result.result = false;
                                        result.errorMessage = "读卡器读取的标签超过一张";
                                    }
                                    else if (listRecv.Count == 0)
                                    {
                                        result.result = false;
                                        result.errorMessage = "读卡器附近没有标签可操作";
                                    }
                                }
                                else
                                {
                                    string cardData = "";
    
    
                                    // edit my mo 2021-1-6 不读取数据。直接返加ID
                                    result.result = true;
                                    result.errorMessage = listRecv[0];
                                    //以下代码读数据是OK的。
                                    //循环读取确保能读到数据
                                    //for (int i = 0; i < 10; i++)
                                    //{
                                    //    result.result = ReadEPCTag(listRecv[0], out cardData, out errMsg);
                                    //    if (result.result)
                                    //    {
                                    //        result.data = cardData;
                                    //        result.errorMessage = listRecv[0];
                                    //    }
                                    //    else
                                    //    {
                                    //        result.result = false;
                                    //        result.errorMessage = errMsg;
                                    //    }
                                    //    if (cardData != "")
                                    //    {
                                    //        break;
                                    //    }
                                    //}
                                    //end   
    
    
                                    /*result.result = ReadEPCTag(listRecv[0], out cardData, out errMsg);
                                    if (result.result)
                                    {
                                        result.errorMessage = listRecv[0];
                                        result.data = cardData;
                                    }
                                    else
                                    {
                                        result.result = false;
                                        result.errorMessage = errMsg;
                                    }*/
                                }
                            }
                            else
                            {
                                result.errorMessage = errMsg;
                            }
    
                            break;
                    }
                    //LogOuts.Info("返回结果:" + JsonHelper.SerializeObject(sd));
                }
                catch (System.Exception ex)
                {
                    result.errorMessage = ex.Message;
                    LogOuts.Info("ex:"+ex.ToString());
                }
    
                try
                {
                    byte[] msgBuffer = BH.WebSocketServer.WebSocket.PackageServerData(JsonHelper.SerializeObject(sd));
                    sockeClient.Send(msgBuffer, msgBuffer.Length, SocketFlags.None);
                }
                catch (Exception ex)
                {
                    LogOuts.Info(ex.Message.ToString());
                }
            }
    
            
    

    6. web通过js 连接socket服务。

    文件名:
    rwinterface.js

    var FUNCIDS = {
        _read:1,
    	_write:2,
    	_getId:3,
    };
    
    
    var SmartReader={
        OBJ:function(){
    		var reader={};
    		var SocketOpen=false;
    		var socket=null;
    		var target=null;
    
            reader.onResult=function(func){
                target.addEvent("Result", func);
            };
            
            var WSonOpen=function(){
                SocketOpen=true;
            };
            var WSonMessage=function(msg){
    			//回调定义,返回json,json有一个data字段,是数据
    			
    			var str = "";
    			str = msg.data;
    			console.log(str);
    			var resultData=eval("("+msg.data+")");
    			resultData.type="Result";
    			if(target!=null){
    				target.fireEvent(resultData);
    			}
            };
            var WSonClose=function(){
                SocketOpen=false;
            };
            var WSonError=function(){
    			SocketOpen=false;
                //alert("RFID读写服务未开启,先下载服务并安装!");
            };
            reader.createSocket=function(){
                try{
                    if ("WebSocket" in window){
                        socket = new WebSocket("ws://localhost:13001/");
                    }
                    else if("MozWebSocket" in window){
                        socket = new MozWebSocket("ws://localhost:13001/");
                    }
                    else{
                        alert("None");
                        return false;
                    }
                    socket.onopen= WSonOpen;
                    socket.onmessage= WSonMessage;
                    socket.onclose= WSonClose;
                    socket.onerror= WSonError;
                    target = new EventTarget();
                    return true;
                }
                catch (ex){
                    return false;
                }
            };
            reader.Disconnect=function(){
                if(socket!=null)
                    socket.close();
            };
    
    		reader.getOBJ = function(id){
    			return reader;
    		};
    
            var SendCmd=function(FunctionID, ParamStr){
    			var entryCmd;
    			if(true == SocketOpen)
    			{
    				entryCmd = {functionId:FunctionID,data:ParamStr}
    				socket.send(JSON.stringify(entryCmd));
    			}
            };
    		reader.write=function(data){
    			if (!SocketOpen){ 
    				alert("RFID读写服务未开启,先下载服务并安装!");
    			}
    			SendCmd(FUNCIDS._write, data);
    		};
    		reader.read=function(){
    			if (!SocketOpen){ 
    				alert("RFID读写服务未开启,先下载服务并安装!");
    			}			
    			SendCmd(FUNCIDS._read);
    		};
            reader.getId=function(){
                if (!SocketOpen){ 
    				alert("RFID读写服务未开启,先下载服务并安装!");
    			}			
    			SendCmd(FUNCIDS._getId);
            }
    
            return reader;
        }
    };
    
    function EventTarget()
    {
        this.handlers = {};
    }
    
    EventTarget.prototype = {
        constructor: EventTarget,addEvent: function(type, handler){
            if(typeof this.handlers[type] == 'undefined'){this.handlers[type] = [];}this.handlers[type].push(handler);
        },fireEvent: function(event){
            if(!event.target){
                event.target = this;
            }
            if(this.handlers[event.type] instanceof Array){
                var handlers = this.handlers[event.type];for(var i = 0; i < handlers.length; i++){
                    handlers[i](event);
                }
            }},removeEvent: function(type, handler){
            if(this.handlers[type] instanceof Array){
                var handlers = this.handlers[type];
                for(var i = 0; i < handlers.length; i++){
                    if(handlers[i] == handler){break;}
                }
                handlers.splice(i, 1);
            }
        }
    };
    
    function _getCmdResult(relPara)
    {
    	var iRel;
    	var separator = relPara.indexOf(",");
    	if(separator != -1)
    	{
    		iRel = relPara.substr(0, separator);
    	}
    	else
    		iRel = relPara.substr(0);	
    
    	return iRel;
    }
    function _getResultPara(relPara)
    {
    	var szPara="";
    	var separator = relPara.indexOf(",");
    	if(separator != -1)
    	{
    		szPara = relPara.substr(separator+1);
    	}
    	return szPara;
    }
    
    try
    {
     var embed_reader = SmartReader.OBJ();
    }
    catch(e)
    {
    }
    
    if(!embed_reader.createSocket())
    {
    }
    
    

    使用:

        <script type="text/javascript" charset="utf-8" src="/js/rwinterface.js?v=1"  charset="utf-8"></script>
            <script type="text/javascript">
              var rfid_obj = embed_reader.getOBJ();
               rfid_obj.onResult(function(rData){
                    var result = rData.data;
                    var cCaseCode = document.getElementById("cCaseCode");
    	            switch(rData.functionId)
                    {
                        case FUNCIDS._getId:
    		                //读取回调
    		                if (result.result)
    		                {
                                 //var str = unescape(result.data.replace(/u/g, "%u"));
    			                //cCaseCode.value=str;  //把返回的
                                $.post("AjaxEdit.aspx",{"iOPType":2,"cID":result.errorMessage},function(data){
                                    var res = data.split('|@|');
                                    if (res[0] == "-1") {
                                        alert(res[1]);
                                        return;
                                    }
                                    else {
                                     //cCaseCode.value=res[1];
                                     getCaseInfo(res[1]);
    
                                    }
                                },"");
                                setTimeout("ReadRFID()",100);
    		                }
    		                else {
                                alert("读RFID出错:" + result.errorMessage);
    		                }
                        break;
    	            }
                    
                });
    
            //读取RFID
            function ReadRFID(){
                rfid_obj.getId();
              
            }
            </script>
        
    
  • 相关阅读:
    [转] css选择器中:first-child与:first-of-type的区别
    [转] Javascript中理解发布--订阅模式
    [转] 浅析JavaScript设计模式——发布-订阅/观察者模式
    [转] linux学习第四十四篇:Nginx安装,Nginx默认虚拟主机,Nginx域名重定向
    [转] meta标签的作用及整理
    [转] 安装npm全局包提示权限不够
    [转] UniCode编码表
    Unicode字符编码表
    [转] Lodash常用API笔记
    [转] JavaScript 之 ArrayBuffer
  • 原文地址:https://www.cnblogs.com/KevinMO/p/14304893.html
Copyright © 2011-2022 走看看