PHP TCP服务端监听端口接收客户端RFID网络读卡器上传的读卡数据

本示例使用设备:WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com)

<?php
header("content-type:text/html;charset=GBK");

set_time_limit(0);
$port=39169;    //监听端口

if(($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE){
    echo '初始化socket失败: ' . socket_strerror(socket_last_error($socket));
    exit;
}

socket_set_nonblock($socket);

// socket_bind(): 将socket资源绑定到指定地址
if(!socket_bind($socket, '0.0.0.0', $port)){
    echo '绑定端口失败: ' . socket_strerror(socket_last_error($socket));
    exit;
}

// socket_listen(): 监听socket的连接请求
if(!socket_listen($socket)){
    echo '监听端口: ' . socket_strerror(socket_last_error($socket));
    exit;
}else{echo "TCP服务已启动,正在侦听端口:".$port."\n";}

while(1){
    if(($client = socket_accept($socket)) !== FALSE){
        while(1){
            //这里不循环的话,只能接收到一次消息
            $content = socket_read($client, 10240);
            $content = trim($content);

            if($content){
                $response = AnalyzeData($content); //解析接收到的数据,并生成回应数据
                socket_write($client, $response);

                $Sendinf='';                    //将发送的信息用16进制数显示,方便调式
                for($i=0;$i<strlen($response);$i++){
                    $byte = ord($response[$i]);
                    $b=substr('00'.dechex($byte ),-2);
                    $Sendinf=$Sendinf.$b.' ';
                }
                echo "发送数据:".$Sendinf."\n\n";
            }
        }
    }
}
socket_close($socket);

//解析接收到的数据,并根据情况生成不同的回应数据
function AnalyzeData($inMsg)
{
    $len = strlen($inMsg);
    $bytes = array();
    $Getinf='';
    for($i=0;$i<$len;$i++)
    {
        $byte = ord($inMsg[$i]);
        $bytes[] =  $byte ;

        $b=substr('00'.dechex($byte ),-2);
        $Getinf=$Getinf.$b.' ';
    }
    echo "接收数据:".$Getinf. PHP_EOL;

    switch($bytes[0]){
        case hexdec('0xF3'):        //接收到设备的心跳数据包,设备心跳间隔可根据协议自行设置
            $Ipaddstr=$bytes[1].".".$bytes[2].".".$bytes[3] .".".$bytes[4] ;
            $Machine=($bytes[5]+$bytes[6]*256) ;
            $frame=($bytes[7]+$bytes[8]*256) ;
            $Heartbeattype=substr('00'.dechex($bytes[9]),-2);
            $heartlen=$bytes[10];
            $switch=substr('00'.dechex($bytes[11]),-2);
            $keyinput=substr('00'.dechex($bytes[12]),-2);
            $Randcode=substr('00'.dechex($bytes[13]),-2).substr('00'.dechex($bytes[14]),-2).substr('00'.dechex($bytes[15]),-2).substr('00'.dechex($bytes[16]),-2);
            $SerialNum="";
            for($i=17;$i<sizeof($bytes);$i++){
                $SerialNum=$SerialNum.substr('00'.dechex($bytes[$i]),-2);
            }
            $Dispinf="数据解析:设备心跳包,设备IP:".$Ipaddstr.",机号:".$Machine.",数据包序号:".$frame.",心跳类型:".$Heartbeattype.",长度:".$heartlen.",继电器状态:".$switch.",按键值:".$keyinput.",随机码:".$Randcode.",硬件序列号:".$SerialNum;
            echo $Dispinf."\n\n";
            break;
        case hexdec('0xC1') or hexdec('0xCF') :     //接收IC读卡器上传的读卡号数据、IC卡离开读卡器的信息
            if($bytes[0]==hexdec('0xC1')){
                $Dispinf="数据解析:IC读卡器读取卡号,";
            }else{$Dispinf="数据解析:IC卡离开读卡器,";}

            $Ipaddstr=$bytes[1].".".$bytes[2].".".$bytes[3] .".".$bytes[4] ;
            $Machine=($bytes[5]+$bytes[6]*256) ;
            $frame=($bytes[7]+$bytes[8]*256) ;
            $Cardlen=$bytes[9];
            $Card16H="";
            for($i=0;$i<$Cardlen;$i++)
            {
                $Card16H=$Card16H.substr('00'.dechex($bytes[10+$i]),-2);
            }
            $CardNo=$bytes[10] & 0xff;
            $CardNo=$CardNo+($bytes[11] & 0xff) *256;
            $CardNo=$CardNo+($bytes[12] & 0xff) *65536;
            $CardNo=$CardNo+($bytes[13] & 0xff) *16777216;
            $CardNo=substr("0000000000".$CardNo,-10);
            $SerialNum ="";
            for($i=10+$Cardlen;$i<$len;$i++){
                $SerialNum=$SerialNum.substr('00'.dechex($bytes[$i]),-2);
            }
            $Dispinf=$Dispinf."设备IP:".$Ipaddstr.",机号:".$Machine.",数据包序号:".$frame.",卡号长度:".$Cardlen.",16进制卡号:".$Card16H.",转十进制卡号:".$CardNo.",硬件序列号:".$SerialNum;
            echo $Dispinf."\n\n";

            //此处加入业务对数据库的查、增、删、减等操作

            $DispStr="卡号:".$CardNo."  ".substr(date('Y-m-d h:i:s', time()),0,16)."            "; //全屏显示信息长度>=34
            return GetResponseData(4,$DispStr); //生成回应数据

            break;
        case hexdec('0xD1') or hexdec('0xDF') :     //接收ID读卡器上传的读卡号数据、ID卡离开读卡器的信息
            if($bytes[0]==hexdec('0xD1')){
                $Dispinf="数据解析:ID读卡器读取卡号,";
            }else{$Dispinf="数据解析:ID卡离开读卡器,";}

            $Ipaddstr=$bytes[1].".".$bytes[2].".".$bytes[3] .".".$bytes[4] ;
            $Machine=($bytes[5]+$bytes[6]*256) ;
            $frame=($bytes[7]+$bytes[8]*256) ;
            $Card16H="";
            for($i=9;$i<14;$i++)
            {
                $Card16H=$Card16H.substr('00'.dechex($bytes[10+$i]),-2);
            }
            $CardNo=$bytes[9] & 0xff;
            $CardNo=$CardNo+($bytes[10] & 0xff) *256;
            $CardNo=$CardNo+($bytes[11] & 0xff) *65536;
            $CardNo=$CardNo+($bytes[12] & 0xff) *16777216;
            $CardNo=substr("0000000000".$CardNo,-10);
            $SerialNum ="";
            for($i=14;$i<$len;$i++){
                $SerialNum=$SerialNum.substr('00'.dechex($bytes[$i]),-2);
            }
            $Dispinf=$Dispinf."设备IP:".$Ipaddstr.",机号:".$Machine.",数据包序号:".$frame.",16进制卡号:".$Card16H.",转十进制卡号:".$CardNo.",硬件序列号:".$SerialNum;
            echo $Dispinf."\n\n";

            //此处加入业务对数据库的查、增、删、减等操作

            $DispStr="卡号:".$CardNo."  ".substr(date('Y-m-d h:i:s', time()),0,16)."            "; //全屏显示信息长度>=34
            return GetResponseData(4,$DispStr); //生成回应数据

            break;
        default:
    }
}

//根据情况生成不同的回应数据
function GetResponseData($respcode,$DispStr)
{
    $sdata = array();
    switch($respcode){
        case 0:     //回只应蜂鸣响声
            $sdata[0] = hexdec('0x96');    //指令码
            $sdata[1] = 0;                          //机号低位,
            $sdata[2] = 0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3] = 1;                          //蜂鸣响声代码,取值范围0-12,代表12种不同的蜂鸣响声
            $sendBuf = '';
            for ($i = 0; $i < 4; $i++) {
                $sendBuf = $sendBuf . chr($sdata[$i]);
            }
            return $sendBuf;
            break;
        case 1:     //回应只开启继电器
            $sdata[0] = hexdec('0x78');    //指令码
            $sdata[1] = 0;                          //机号低位,
            $sdata[2] = 0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3] = hexdec('0xF0');    //继电器代码 F0表示全部继电器、F1表示1号继电器 、F2表示2号继电器、F3表示3号继电器......
            $sdata[4] = hexdec('0x2C');    //继电器开启延时低位16进制
            $sdata[5] = hexdec('0x01');    //继电器开启延时高位16进制,高低位取值FFFF表示继电器一直开启
            $sendBuf = '';
            for ($i = 0; $i < 6; $i++) {
                $sendBuf = $sendBuf . chr($sdata[$i]);
            }
            return $sendBuf;
            break;
        case 2:     //回应只关闭已开启的继电器
            $sdata[0] = hexdec('0x78');    //指令码
            $sdata[1] = 0;                          //机号低位,
            $sdata[2] = 0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3] = hexdec('0xE0');    //继电器代码 E0表示全部继电器、E1表示1号继电器 、E2表示2号继电器、E3表示3号继电器......
            $sdata[4] = hexdec('0x2C');    //继电器关闭延时低位16进制
            $sdata[5] = hexdec('0x01');    //继电器关闭延时高位16进制,高低位取值FFFF表示继电器一直关闭
            $sendBuf = '';
            for ($i = 0; $i < 6; $i++) {
                $sendBuf = $sendBuf . chr($sdata[$i]);
            }
            return $sendBuf;
            break;
        case 3:     //回应蜂鸣响声+文字显示
            $sdata[0]=hexdec('0x5A');    //指令码
            $sdata[1]=0;                          //机号低位
            $sdata[2]=0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3]=2;                          //蜂鸣声代码,取值范围0-12,代表12种不同的蜂鸣响声
            $sdata[4]=20;                         //显示时长,单位秒,取值范围0-255,取值255时表示永久显示
            $sendBuf='';
            for($i=0;$i<5;$i++)
            {
                $sendBuf=$sendBuf.chr($sdata[$i]);
            }
            $sendBuf=$sendBuf.$DispStr;
            return $sendBuf;
            break;
        case 4:     //回应蜂鸣响声+继电器开关+文字显示+播报TTS语音
            $SpeakStr="[v10]";                    //[v10]是语音大小,取值范围0-16,可加在任何地方,其他语音策略请看文档说明
            $SpeakStr=$SpeakStr."刷卡成功,感谢您使用我们的网络读卡器!";//要播报的TTS语音,每条指令最大不能超过126字符
            $Splen = strlen($SpeakStr);           //TTS语音长度
            //
            $sdata[0]=hexdec('0x5C');    //指令码
            $sdata[1]=0;                          //机号低位
            $sdata[2]=0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3]=2;                          //蜂鸣声代码,取值范围0-12,代表12种不同的蜂鸣响声
            $sdata[4]=hexdec('0xF0');    //继电器代码 F0表示全部继电器 F1表示1号继电器 F2表示2号继电器

            $sdata[5]=hexdec('0x2C');    //继电器开启时长低位
            $sdata[6]=hexdec('0x01');    //继电器开启时长高位

            $sdata[7]=hexdec('0x14');    //显示保留时间,单位为秒,为0xFF时表示永久显示
            $sdata[8]=0;                          //在显示屏中的哪个位置开始
            $sdata[9]=hexdec('0x22');    //显示字符串长度 为全屏显示为 34 个字符
            $sdata[10]=$Splen;                    //语音长度

            $suffixStr=chr(hexdec('0x55')).chr(hexdec('0xaa')).chr(hexdec('0x66')).chr(hexdec('0x99'));  //固定的抗干扰后缀

            $sendBuf='';
            for($i=0;$i<11;$i++)
            {
                $sendBuf=$sendBuf.chr($sdata[$i]);
            }
            $sendBuf=$sendBuf.substr($DispStr,0,34).$SpeakStr.$suffixStr;   //最长显示34个字符

            return $sendBuf;
            break;
        default:
    }
}

//获取本机IP地址------------------------------------------------------------------------------------------------------------------------
function get_local_ip()
{
    $preg = "/\A((([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\.){3}(([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\Z/";
    //获取操作系统为win2000/xp、win7的本机IP真实地址
    $Netdriv=array();
    exec("ipconfig", $out, $stats);
    if (!empty($out)) {
        foreach ($out AS $row) {
            if (strstr($row, "IP") && strstr($row, ":") && !strstr($row, "IPv6")) {
                $tmpIp = explode(":", $row);
                if (preg_match($preg, trim($tmpIp[1]))) {
                    $Netdriv[]=trim($tmpIp[1]);
                    echo trim($tmpIp[1])."\n";
                }
            }
        }
    }
    //获取操作系统为linux类型的本机IP真实地址
    //exec("ifconfig", $out, $stats);
    //if (!empty($out)) {
    //    if (isset($out[1]) && strstr($out[1], 'addr:')) {
    //        $tmpArray = explode(":", $out[1]);
    //        $tmpIp = explode("", $tmpArray[1]);
    //        if (preg_match($preg, trim($tmpIp[0]))) {
    //            return trim($tmpIp[0]);
    //        }
    //    }
    //}
    if (!empty($Netdriv)) {
        return $Netdriv[0];   //如果有多张网块,可以修改数组取值来绑定相应的网卡
    }else{
        return '127.0.0.1';
    }
}

?>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/193468.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java线程同步

认识线程同步 解决方案 方法一&#xff1a;同步代码块 package com.itheima.d3;public class ThreadTest {public static void main(String[] args) {Accout acc new Accout("ICBC-110",100000);new DrawThread(acc,"小明").start();//小明new DrawThread…

OpenAI神秘项目Q-star曝光,人类永生或灭绝,将在我们有生之年发生

上周&#xff0c;OpenAI人事风波暂停的尾声中&#xff0c;有个“可能威胁人类”的、代号为“Q*”的神秘项目被抛掷出来。 传言中&#xff0c;Sam Altman被解雇前&#xff0c;几名研究人员向董事会发了一封信&#xff0c;警告一项强大的人工智能发现可能威胁到人类&#xff0c;而…

使用 Java 来读取 Excel 文件,检查每一行中的 URL,并将不符合条件的行标记为红色

-- 日、时、分、秒&#xff0c;这是计时的单位&#xff0c;惜时就应该惜日、惜时、惜分、惜秒。 用 Java 来读取 Excel 文件&#xff0c;检查每一行中的 URL&#xff0c;并将不符合条件的行标记为红色。以下是一个简单的示例&#xff0c;使用 Apache POI 进行 Excel 操作&#…

数据结构与算法编程题31

判断给定二叉树是否是完全二叉树 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 #define Maxsize 100 #define STR_SIZE 1024typedef struct BiTNode {ElemType data;BiTNode* lchild, …

ref详解(C#)

本质上来说 ref 的就是把 C/C 指针的那一套又拿回来了&#xff0c;而且还封装成一套自己的玩法。 我想设计者的初心把 ref 的功能限制得死死的&#xff0c;可能也考虑到 C# 是一门面向业务开发的语言&#xff0c;讲究的是做项目快狠准&#xff0c;性能反而不是第一要素&#x…

进程等待讲解

今日为大家分享有关进程等待的知识&#xff01;希望读完本文&#xff0c;大家能有一定的收获&#xff01; 正文开始&#xff01; 进程等待的引进 既然我们今天要讲进程等待这个概念&#xff01;那么只有我们把下面这三个方面搞明白&#xff0c;才能真正的了解进程等待&#x…

[Spring ~必知必会] Bean 基础常识汇总

文章目录 Bean 相关到底什么是beanFactorybeanFactory能干啥ApplicationContext是什么ApplicationContext的功能比 BeanFactory多了什么 容器的实现BeanFactory的实现ApplicationContext的实现xml 配置配置类配置 Bean 的生命周期3.1 Bean 的常见的后处理器测试代码总结 3.2 工…

数据结构 | TOP-K问题

数据结构 | TOP-K问题 文章目录 数据结构 | TOP-K问题随机生成一些数据&#xff0c;找前k个最大值进行取前k个值建堆找到了前k个结果以及全部代码 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大。 就是从N个数里面找…

P14 C++局部静态变量static延长生命周期

目录 01 前言 02 变量的作用域与生命周期 2.1 什么是作用域&#xff1a; 2.2 什么是变量的生命周期&#xff1a; 03 局部静态 3.1非静态变量例子 3.2静态变量例子 04 全局变量 05 后话 01 前言 在前几期里&#xff0c;我们了解了static关键字在特定上下文中的含义。 …

innovus如何在floorplan view显示所有module

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 如题&#xff0c;innovus的图形界面在floorplan view下默认只能显示instance数量超过100个的module&#xff0c;如果要显示更小的module&#xff0c;需要在VIEW-Set Perference…

分享从零开始学习网络设备配置--任务4.3 使用动态路由RIPng实现网络连通

任务描述 某公司使用IPv6技术搭建企业网络&#xff0c;由于静态路由需要管理员手工配置&#xff0c;在网络拓扑发生变化时&#xff0c;也不会自动生成新的路由&#xff0c;因此采用IPv6动态路由协议RIPng实现网络连通&#xff0c;实现任意两个节点之间的通信&#xff0c;并降低…

堆的应用:堆排序

文章目录 前言堆排序的实现&#xff08;升序为例&#xff09;代码 前言 堆排序&#xff0c;顾名思义是一个利用堆来完成排序的一个操作。在之前&#xff0c;小编在[C语言学习系列–&#xff1e;【关于qsort函数的详解以及它的模拟实现】] 谈到冒泡排序&#xff0c;但是冒泡排序…

京东秒杀之秒杀详情

1 编写前端页面&#xff08;商品详情&#xff09; <!DOCTYPE html> <head><title>商品详情</title><meta http-equiv"Content-Type" content"text/html; charsetUTF-8" /><script type"text/javascript" src&…

GPU集群使用Tip:查询端口号占用情况、进程由哪个用户创建、运行时指定某一张显卡

在GPU集群上运行代码&#xff0c;会面临一些问题&#xff1a; &#xff08;1&#xff09;跑着跑着GPU memory分配失败 – 因为有其他人在使用 &#xff08;2&#xff09;运行时显示端口号已被占用&#xff0c;需要你换一个端口。 这个时候一般采取的方法有&#xff1a; &#x…

java springboot测试类Transactional解决 测试过程中在数据库留下测试数据问题

好 目前 我们已经完成了表现层对应的测试了 但这里有个坑 如果我们在执行某个声明周期时 包含了测试的过程 它会在数据库中留下一条数据 但真实企业开发 绝对不允许 过一遍留一组数据的 那么 我们的期望就是 执行测试过程 但不要留下任何数据 这是我们的数据库表 然后 这里…

帆软报表 channel 反序列化漏洞复现

0x01 产品简介 FineReport、FineBI 是帆软软件开发的企业级报表设计和数据分析工具与商业智能平台。 0x02 漏洞概述 帆软FineReport、FineBI 存在反序列化漏洞&#xff0c;攻击者可向 /webroot/decision/remote/design/channel 接口发送精心构造的反序列化数据&#xff0c;在目…

E云管家微信群聊机器人开发

请求URL&#xff1a; http://域名地址/modifyGroupRemark 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId是String登录实例标识chatRo…

【html+css】表单元素

目录 表单元素 展示图 简约写法&#xff1a; 完美写法 表单元素 输入框 单选框 复选框 下拉框 按钮 展示图 简约写法&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><t…

域名邮箱与企业邮箱的区别:功能、应用与优势

根据使用者的不同需求&#xff0c;电子邮件分为域名邮箱和企业邮箱两种类型。那么这两种邮箱之间究竟存在哪些区别呢&#xff1f;本文将从定义、优势和劣势三个方面进行详细解析。 什么是域名邮箱&#xff1f; 域名邮箱&#xff0c;顾名思义是以域名作为后缀的电子邮箱。域名邮…

第二十五章 解析cfg文件及读取获得网络结构

网络结构 以YOLOv3_SPP为例 cfg文件 部分&#xff0c;只是用来展示&#xff0c;全部的代码在文章最后 [net] # Testing # batch1 # subdivisions1 # Training batch64 subdivisions16 width608 height608 channels3 momentum0.9 de…