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小程序;
干洗店洗鞋店管理系统是一款专业的洗衣店管理软件,集成了前台收费收银系统、会员卡管理系统和财务报表系统等强大功能。界面简洁优美,操作直观简单。这款系统为干洗店和洗衣店提供了成本分析、利润分析、洗衣流程管理等诸多实用功能,用全新的…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...