Java TCP服务端多线程接收RFID网络读卡器上传数据

本示例使用设备介绍:WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;public class TCPServer_Java {//监听端口private static final int PORT = 39169;public static void main(String[] args) throws IOException {ServerSocket serverSocket = null;Socket socket = null;try {//建立服务器的Socket,并设定一个监听的端口PORTserverSocket = new ServerSocket(PORT);//由于需要进行循环监听,因此获取消息的操作应放在一个while大循环中while(true){try {//建立跟客户端的连接socket = serverSocket.accept();ServerThread thread = new ServerThread(socket);thread.start();} catch (Exception e) {System.out.println("建立与客户端的连接出现异常");e.printStackTrace();}//ServerThread thread = new ServerThread(socket);//thread.start();}} catch (Exception e) {System.out.println("端口被占用");e.printStackTrace();}finally {serverSocket.close();}}
}//服务端线程类
//继承Thread类的话,必须重写run方法,在run方法中定义需要执行的任务。
class ServerThread extends Thread {private Socket socket ;InputStream inputStream;OutputStream outputStream;public ServerThread(Socket socket){this.socket=socket;}public void run(){try {while (true){//接收客户端的消息,解析信息并回应读卡器//System.out.println(socket);byte[] bytes =new byte[1024];inputStream =socket.getInputStream();int GetDataLen=0;while ((GetDataLen=inputStream.read(bytes))!=-1){ //通过这个方法读取全部数据 及 长度,break;}if(GetDataLen>0) {String bytestr = "";String DataStr = "";String DispStr = "";String CardNo16 = "";String SerialNum = "";long cardno10;long cardnum;for (int p = 0; p < GetDataLen; p++) {bytestr = "00" + Integer.toHexString(bytes[p] & 0xff);DataStr = DataStr + bytestr.substring(bytestr.length() - 2, bytestr.length()) + " ";}System.out.println("Received from " + socket.getRemoteSocketAddress() + " : " + DataStr);switch (bytes[0]) {case (byte)0xc1:case (byte)0xcf:if(bytes[0]==(byte)0xc1){DispStr = "数据解析:接收到读取IC卡号信息,";}else{DispStr = "数据解析:接收到IC卡离开读卡器,";}DispStr = DispStr + "功能码:" + Integer.toHexString(bytes[0] & 0xff);DispStr = DispStr + ",设备IP:" + Integer.toString(bytes[1] & 0xff) + "." + Integer.toString(bytes[2] & 0xff) + "." + Integer.toString(bytes[3] & 0xff) + "." + Integer.toString(bytes[4] & 0xff);DispStr = DispStr + ",机号:" + Integer.toString((bytes[5] & 0xff) + ((bytes[6] & 0xff) * 256));DispStr = DispStr + ",数据包序号:" + Integer.toString((bytes[7] & 0xff) + ((bytes[8] & 0xff) * 256));int Cardlen = bytes[9];DispStr = DispStr + ",卡号长度:" + Integer.toString(Cardlen);CardNo16 = "";for (int p = 10; p < 10 + Cardlen; p++) {bytestr = "00" + Integer.toHexString(bytes[p] & 0xff);CardNo16 = CardNo16 + bytestr.substring(bytestr.length() - 2, bytestr.length());}DispStr = DispStr + ",16进制卡号:" + CardNo16;cardnum = bytes[10] & 0xff;cardnum = cardnum + (bytes[11] & 0xff) * 256;cardnum = cardnum + (bytes[12] & 0xff) * 65536;cardnum = cardnum + (bytes[13] & 0xff) * 16777216;cardno10 = 0;for (int j = 28; j >= 0; j -= 4) {cardno10 = cardno10 << 4 | (cardnum >>> j & 0xF);}DispStr = DispStr + ",转10进制卡号:" + String.format("%010d", cardno10);SerialNum = "";for (int p = 10 + Cardlen; p < GetDataLen; p++) {bytestr = "00" + Integer.toHexString(bytes[p] & 0xff);SerialNum = SerialNum + bytestr.substring(bytestr.length() - 2, bytestr.length());}DispStr = DispStr + ",唯一硬件序号:" + SerialNum;System.out.println(DispStr + "\n");//向客户端发送消息byte[] RespByte=GetResponseData(2); //生成不同的回应数据包outputStream = socket.getOutputStream();outputStream.write(RespByte);bytestr = "";DataStr = "";for (int p = 0; p < RespByte.length; p++) {bytestr = "00" + Integer.toHexString(RespByte[p] & 0xff);DataStr = DataStr + bytestr.substring(bytestr.length() - 2, bytestr.length()) + " ";}System.out.println("Send Data To "+socket.getRemoteSocketAddress()+" : "+DataStr+"\n");break;case (byte)0xd1:case (byte)0xdf:if(bytes[0]==(byte)0xd1){DispStr="数据解析:接收到读取ID卡号信息,";}else{DispStr="数据解析:接收到ID卡离开读卡器,";}DispStr=DispStr+"功能码:"+ Integer.toHexString(bytes[0] & 0xff);DispStr=DispStr+",设备IP:"+ Integer.toString(bytes[1] & 0xff) + "." + Integer.toString(bytes[2] & 0xff) + "." + Integer.toString(bytes[3] & 0xff) + "." + Integer.toString(bytes[4] & 0xff);DispStr=DispStr+",机号:"+ Integer.toString((bytes[5] & 0xff) + ((bytes[6] & 0xff) * 256));DispStr=DispStr+",数据包序号:"+ Integer.toString((bytes[7] & 0xff) + ((bytes[8] & 0xff) * 256));CardNo16="";for (int p = 9; p < 14; p++) {bytestr = "00" + Integer.toHexString(bytes[p] & 0xff);CardNo16 = CardNo16 + bytestr.substring(bytestr.length() - 2, bytestr.length());}DispStr=DispStr+",16进制卡号:"+CardNo16;cardnum = bytes[9] & 0xff;cardnum = cardnum + (bytes[10] & 0xff) * 256;cardnum = cardnum + (bytes[11] & 0xff) * 65536;cardnum = cardnum + (bytes[12] & 0xff) * 16777216;cardno10 = 0;for (int j = 28; j >= 0; j -= 4) {cardno10 = cardno10 << 4 | (cardnum >>> j & 0xF);}DispStr=DispStr+",转10进制卡号:"+ String.format("%010d", cardno10);SerialNum="";for (int p = 14; p < GetDataLen; p++) {bytestr = "00" + Integer.toHexString(bytes[p] & 0xff);SerialNum = SerialNum + bytestr.substring(bytestr.length() - 2, bytestr.length());}DispStr=DispStr+",唯一硬件序号:"+ SerialNum;System.out.println(DispStr+"\n");//向客户端发送消息RespByte=GetResponseData(2); //生成不同的回应数据包outputStream = socket.getOutputStream();outputStream.write(RespByte);bytestr = "";DataStr = "";for (int p = 0; p < RespByte.length; p++) {bytestr = "00" + Integer.toHexString(RespByte[p] & 0xff);DataStr = DataStr + bytestr.substring(bytestr.length() - 2, bytestr.length()) + " ";}System.out.println("Send Data To "+socket.getRemoteSocketAddress()+" : "+DataStr+"\n");break;case (byte)0xf3:DispStr="数据解析:接收到设备心跳包,";DispStr=DispStr+"功能码:"+Integer.toHexString(bytes[0] & 0xff);DispStr=DispStr+",设备IP:"+Integer.toString(bytes[1] & 0xff)+"."+Integer.toString(bytes[2] & 0xff)+"."+Integer.toString(bytes[3] & 0xff)+"."+Integer.toString(bytes[4] & 0xff);DispStr=DispStr+",机器号:"+Integer.toString((bytes[5] & 0xff)+((bytes[6] & 0xff) *256));DispStr=DispStr+",包序号:"+Integer.toString((bytes[7] & 0xff)+((bytes[8] & 0xff) *256));DispStr=DispStr+",心跳码:"+Integer.toHexString(bytes[9] & 0xff);DispStr=DispStr+",长 度:"+Integer.toHexString(bytes[10] & 0xff);DispStr=DispStr+",继电器:"+Integer.toHexString(bytes[11] & 0xff);DispStr=DispStr+",按键值:"+Integer.toHexString(bytes[12] & 0xff);for(int p=13;p<17;p++){bytestr="00"+Integer.toHexString(bytes[p] & 0xff);SerialNum=SerialNum+ bytestr.substring(bytestr.length() -2,bytestr.length());}DispStr=DispStr+",随机码:"+SerialNum;SerialNum="";for(int p=17;p<GetDataLen;p++){bytestr="00"+Integer.toHexString(bytes[p] & 0xff);SerialNum=SerialNum+ bytestr.substring(bytestr.length() -2,bytestr.length());}DispStr=DispStr+",设备序列号:"+SerialNum;System.out.println(DispStr+"\n");break;}}}} catch (Exception e) {System.out.println("客户端主动断开连接了");e.printStackTrace();}//操作结束,关闭sockettry{socket.close();}catch(IOException e){System.out.println("关闭连接出现异常");e.printStackTrace();}}//根据Respcode返回不同的回应数据包static byte[] GetResponseData(int Respcode) throws Exception {byte[] RespByte= new byte[300];String DispStr="本次刷卡成功,感谢您的使用,再见! "; //满屏显示34个字符,不足后面加空格byte[] DispBuf;switch(Respcode){case 0: //驱动读卡器蜂鸣响声RespByte[0] = (byte) 0x96; //蜂鸣响声的指令码RespByte[1] = (byte) 0x00; //机号低位RespByte[2] = (byte) 0x00; //机号高,0000表示任意机号RespByte[3] = (byte) 0x01; //蜂鸣响声代码,取值范围0-12RespByte = Arrays.copyOf(RespByte, 4);break;case 1: //驱动读卡器显示文字+蜂鸣响声DispBuf= DispStr.getBytes("gb2312"); //显示文字转字节数组RespByte[0]=(byte)0x5a; //指令码RespByte[1]=(byte)0x00; //机号低RespByte[2]=(byte)0x00; //机号高,如果高低位都为0表示任意机号RespByte[3]=(byte)0x02; //蜂鸣声代码RespByte[4]=(byte)0x14; //显示时长for(int i=0;i<34;i++){ //显示文字RespByte[i+5]=DispBuf[i];}RespByte = Arrays.copyOf(RespByte, 39);break;case 2: //驱动读卡器显示文字+蜂鸣响声+继电器开关+TTS语音DispBuf= DispStr.getBytes("gb2312"); //显示文字转字节数组String SpeakStr=""; //将要播报的TTS语音生成字节数组,最大不能超过126个字节SpeakStr="[v1]"; //定义语音大小,取值范围v0 到 v16,可加在任何地方SpeakStr=SpeakStr+"欢迎您使用我们的网络读卡器,谢谢!"; //要播报的中文语音byte[] SpeakBuf= SpeakStr.getBytes("gb2312");int SpeakLen=SpeakBuf.length; //语音长度int SendLen=11+34+SpeakLen+4; //总计发送数据长度RespByte[0]=(byte)0x5C; //指令码RespByte[1]=(byte)0x00; //机号低RespByte[2]=(byte)0x00; //机号高,如果高低位都为0表示任意机号RespByte[3]=(byte)0x01; //蜂鸣声代码RespByte[4]=(byte)0xF0; //继电器代码 F0表示全部继电器 F1表示1号继电器 F2表示2号继电器RespByte[5]=(byte)0x20; //继电器开启时长 低位RespByte[6]=(byte)0x00; //继电器开启时长 高位RespByte[7]=(byte)0x14; //显示保留时间,单位为秒,为0xFF时表示永久显示RespByte[8]=(byte)0x00; //在显示屏中的哪个位置开始RespByte[9]=(byte)0x22; //显示字符串长度 为全屏显示为 34 个字符RespByte[10]=(byte)SpeakLen; //语音长度for(int i=0;i<34;i++){ //显示的文字信息RespByte[i+11]=DispBuf[i];}for(int i=0;i<SpeakLen;i++){ //TTS语音播报信息RespByte[i+45]=SpeakBuf[i];}RespByte[10+34+SpeakLen+1]=(byte)0x55; //固定的抗干扰后缀RespByte[10+34+SpeakLen+2]=(byte)0xaa;RespByte[10+34+SpeakLen+3]=(byte)0x66;RespByte[10+34+SpeakLen+4]=(byte)0x99;RespByte = Arrays.copyOf(RespByte, 10+34+SpeakLen+5);break;case 3: //驱动读卡器开启继电器开关RespByte[0]=(byte)0x78; //指令码RespByte[1]=(byte)0x00; //机号低RespByte[2]=(byte)0x00; //机号高,如果高低位都为0表示任意机号RespByte[3]=(byte)0xF0; //继电器代码 F0表示全部继电器、F1表示1号继电器 、F2表示2号继电器......RespByte[4]=(byte)0x2C; //继电器开启延时低位RespByte[5]=(byte)0x01; //继电器开启延时高位,FFFF表示继电器一直开启RespByte = Arrays.copyOf(RespByte, 6);break;default:}return RespByte;}
}
相关文章:
Java TCP服务端多线程接收RFID网络读卡器上传数据
本示例使用设备介绍:WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com) import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; impor…...
SpringCloud——服务网关——GateWay
1.GateWay是什么? gateway也叫服务网关,SpringCloud GateWay使用的是Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。 gateway的功能有反向代理、鉴权、流量控制、熔断、日志监控...... 2.为什么不使用Zuul?…...
Linux程序的地址空间
Linux程序的地址空间 📟作者主页:慢热的陕西人 🌴专栏链接:Linux 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 本博客主要内容深刻理解了什么程序或者进程的地址…...
Docker安装Minio(稳定版)
1、安装 docker pull minio/minio:RELEASE.2021-06-17T00-10-46Z docker run -p 9000:9000 minio/minio:RELEASE.2021-06-17T00-10-46Z server /data 2、访问测试 3、MinIO自定义Access和Secret密钥 要覆盖MinIO的自动生成的密钥,您可以将Access和Secret密钥设为…...
大数据毕业设计选题推荐-超级英雄运营数据监控平台-Hadoop-Spark-Hive
✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...
视频转码教程:轻松制作GIF动态图,一键高效剪辑操作
随着社交媒体的兴起,GIF动态图已经成为了人们表达情感、分享精彩瞬间的重要方式。而将视频转化为GIF动态图,不仅可以方便地在社交媒体上分享,还可以延长视频的播放时长,吸引更多的观众。本篇文章将为大家介绍如何将视频轻松转化为…...
Seata分布式事务实现原理
Seata可以解决分布式事务问题,利用GlobalTransacational(name "fsp-create-order",rollbackFor Exception.class)注解就可以实现全局的事务管理,但是我们需要明白原理的实现。 我们举例创建订单——>调减库存——>调扣余额——>改订…...
Rasa NLU中的组件
Rasa NLU部分主要是解决NER(序列建模)和意图识别(分类建模)这2个任务。Rasa NLP是一个基于DAG的通用框架,图中的顶点即组件。组件特征包括有顺序关系、可相互替换、可互斥和可同时使用。有向无环图(DAG&…...
redis笔记 三 redis持久化
文章目录 Redis持久化RDB持久化执行时机RDB原理小结 AOF持久化AOF原理AOF配置AOF文件重写 RDB与AOF对比 Redis持久化 redis持久化是为了解决redis宕机时丢失数据的问题,Redis有两种持久化方案: RDB持久化AOF持久化 RDB持久化 RDB全称Redis Database …...
k8s-----数据存储
目录 一、数据存储的概念 二、基本存储 1、EmptyDir存储卷 2、hostPath存储卷 3、nfs共享存储卷 三、高级存储 1、PV(持久化卷) 2、PVC(持久化卷声明) 3、静态PV实验 4、动态PV实验 4.1 在stor01节点上安装nfs…...
macOS电池续航工具:Endurance中文
Endurance for Mac是一款强大而实用的电池管理和优化软件,专为MacBook设计。通过智能调整系统设置和管理后台应用,它能有效延长电池续航时间,提升工作和娱乐效率,成为你在各种场合下的得力助手。 Endurance for Mac软件的功能特色…...
栈(定义,基本操作,顺序存储,链式存储)
目录 1.栈的定义1.重要术语2.特点 2.栈的基本操作3.栈的顺序存储1.顺序栈的定义2.基本操作1.初始化2.进栈3.出栈4.读栈顶 3.共享栈 4.栈的链式存储 1.栈的定义 栈( Stack)是只允许在一端进行插入或删除操作的线性表。 一种受限的线性表,只能在栈顶进行插…...
在HTML单页面中,使用Bootstrap框架的多选框如何提交数据
1.引入Bootstrap CSS和JavaScript文件:确保在HTML页面的标签内引入Bootstrap的CSS和JavaScript文件。可以使用CDN链接或者下载本地文件。 <link rel"stylesheet" href"https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css&q…...
当爱好变成职业,会不会就失去了兴趣?
当爱好变成职业,会不会就失去了兴趣? 当兴趣变成职业 1、学习能力变强了,积极主动性增加了。 2、学习努力变现了,赚到的更钱多了。 3、赚钱能力变强了,反过来再次促使兴趣发展(兴趣更大了....干劲更足了&…...
3-知识补充-MVC框架
3-知识补充-MVC框架 文章目录 3-知识补充-MVC框架MVC概述M、V、C各自负责功能及常用包MVC框架图非前后端分离框架图前后端分离框架图 MVC概述 MVC(Model、View、Controller)是软件工程中的一种**软件架构模式,它把软件系统分为模型、视图和控…...
leetcode:141. 环形链表
一、题目 函数原型: bool hasCycle(struct ListNode *head) 二、算法 判断不是环形链表,只需遍历链表找到空结点即可。 判断是环形链表,由于链表是环形的,遍历不会永远不会结束。所以要设置快慢指针,慢指针一次走一步&…...
了解企业邮箱的外观和功能特点
企业邮箱是什么样子的?企业邮箱不是单一产品,而是由一系列电子邮件服务组成的生态系统。这些服务包括但不限于邮件服务器、客户端、安全解决方案等。这些服务共同构成了企业邮箱的基础设施。 在外观上,企业邮箱和个人邮箱没有太大区别。用户通…...
配置阿里云镜像加速器 -docker
1.百度aliyun 2.找到镜像服务ACR 3.搞一个个人版,身份验证一下就行了很简单 4.找到镜像加速器Centos 5.执行下面4条命令:4条命令直接从上面操作文档中粘贴,不容易出错 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<…...
11 抽象向量空间
抽象向量空间 向量是什么函数什么是线性推论向量空间 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 向量是什么 可以是一个箭头,可以是一组实数,即一个坐标对。 箭头在高维(4维,甚至更高)空间&…...
干洗店洗鞋店管理系统app小程序;
干洗店洗鞋店管理系统是一款专业的洗衣店管理软件,集成了前台收费收银系统、会员卡管理系统和财务报表系统等强大功能。界面简洁优美,操作直观简单。这款系统为干洗店和洗衣店提供了成本分析、利润分析、洗衣流程管理等诸多实用功能,用全新的…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
