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

news2024/10/6 4:06:47

本示例使用设备介绍: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,并设定一个监听的端口PORT
            serverSocket = 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();
        }

        //操作结束,关闭socket
        try{
            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-12
                RespByte = 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;
    }
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue路由介绍及使用

一、单页应用程序介绍 1.概念 单页应用程序&#xff1a;SPA【Single Page Application】是指所有的功能都在一个html页面上实现&#xff0c;当切换不同的功能时&#xff0c;页面不会进行刷新&#xff0c;类似Ajax请求&#xff0c;但请求地址会发生部分变化。 2.具体示例 单…

微型计算机原理1

一、选择题 1.8086CPU的字长是&#xff08;&#xff09;位。 A. 32 B. 128 C. 64 D. 16 2 间接寻址方式中&#xff0c;操作数在(&#xff09;中。 A. 通用寄存器 B. 内存单元 C. 程序计数器 D.堆栈 3.在循环指令LOOP和串操作指令中,用作计数器的寄存器是() A. AX B. BX C. C…

深度学习(CNN+RNN)笔记1

文章目录 视频课 第四课&#xff1a;卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第一周&#xff1a;Convolutional Neural Networks 卷积神经网络第二周&#xff1a;Case Studies 案例学习第三周&#xff1a;Object Detection 目标检测第四周&#xff…

Jupyter Notebook快速上手

Jupyter Notebook快速上手 文章目录 Jupyter Notebook快速上手1 运行Jupyter Notebook1.1 通过图形化界面打开1.2 通过命令行打开1.3 在指定项目目录下打开 2 Jupyter Notebook运行后无法自动打开网页3 Jupyter Notebook运行代码没反应4 退出4.1 终端退出4.2 命令行退出 此教程…

[PHP]ShopXO企业级B2C免费开源商城系统 v2.3.1

ShopXO 企业级B2C免费开源电商系统&#xff01; 求实进取、创新专注、自主研发、国内领先企业级B2C电商系统解决方案。 遵循Apache2开源协议发布&#xff0c;无需授权、可商用、可二次开发、满足99%的电商运营需求。 PCH5、支付宝小程序、微信小程序、百度小程序、头条&抖音…

Chrome插件精选 — 屏幕录像插件

Chrome实现同一功能的插件往往有多款产品&#xff0c;逐一去安装试用耗时又费力&#xff0c;在此为某一类型插件挑选出比较好用的一款或几款&#xff0c;尽量满足界面精致、功能齐全、设置选项丰富的使用要求&#xff0c;便于节省一个个去尝试的时间和精力。 1. 屏幕录像机 - S…

Java GC机制 —— 个人笔记

文章目录 JVM内存区对象是否需要回收&#xff1f;1. 引用计数法2. 可达性分析法&#xff08;根搜索算法&#xff09;Java的引用 对象何时被回收&#xff1f;回收策略回收策略1&#xff1a;引用计数算法回收策略2&#xff1a;标记清除算法&#xff08;Mark-Sweep&#xff09;回收…

MySQL 8.0 Clone Plugin 详解

文章目录 前言1. 克隆插件安装2. 克隆插件的使用2.1 本地克隆2.2 远程克隆 3. 克隆任务监控4. 克隆插件实现4.1 Init 阶段4.2 File Copy4.3 Page Copy4.4 Redo Copy4.5 Done 5. 克隆插件的限制6. 克隆插件与 Xtrabackup 的异同7. 克隆插件相关参数后记 前言 克隆插件&#xff…

武汉某母婴用品公司 - 集简云连接ERP和营销系统,实现库存管理的自动化

品牌介绍与关怀理念 武汉某母婴用品公司是一家专注于高端孕婴童护理用品的企业&#xff0c;积极响应和关怀孕产人群&#xff0c;全方位提供从待产用品到产后护理用品&#xff0c;再到婴童洗护用品和初生婴儿用品等一系列全面的母婴产品。我们的使命是满足客户的需求&#xff0…

光学仿真 | 仿真推动以人类视觉感知为本的汽车显示设计

如果产品设计无法使终端用户产生共鸣&#xff0c;就不会存在卓越的工程设计。您可以设计一种结构坚固的方向盘&#xff0c;但如果它被放在错误的位置&#xff0c;就无法实现其用于转向的主要目的。 同样&#xff0c;在围绕人类视觉进行设计时&#xff0c;显示器其实无需具备尽…

分布式任务调度(01)--分布式锁

Quartz集群模式可水平扩展&#xff0c;也可分布式调度&#xff0c;但需业务方在数据库中添加对应表&#xff0c;有强侵入性。于是探索分布式锁模式。 1 超时关单 通常做定时任务每2min检查前半小时的订单&#xff0c;将待支付订单列表查出&#xff0c;然后对订单中的商品进行…

数据结构(c语言版) 队列

链队列 要求&#xff1a;实现链队列的创建、初始化、入队、出队 &#xff08;先进先出&#xff09; 代码 // // Created by My.cy on 2023/10/19. // //链队列 创建、初始化、入队、出队 先进先出#include <stdio.h> #include <malloc.h>//定义结构体 struct…

【电源专题】PSE如何与PD握手协商功率等级?

在文章:【电源专题】POE连接方式与功率等级划分 中我们讲到POE协议对不同的PD设备进行划分,比如根据不同的供电标准又可以细分成好几种不同的类型(Type1~Type4)和功率等级。 那么有这么多功率等级,PSE怎么知道PD是哪种类型呢?怎么能进行握手协商呢? 下图为PSE与PD设备在…

Linux学习第36天:Linux RTC 驱动实验:时间是一条流淌的河

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 RTC就是实时时钟。 本笔记主要学习Linux RTC驱动试验&#xff0c;主要内容包括Linux内核RTC驱动简介、I.MX6U内部RTC分析、RTC时间查看与设置。因为Linux内核已经…

用 bitsandbytes、4 比特量化和 QLoRA 打造亲民的 LLM

众所周知&#xff0c;LLM 规模庞大&#xff0c;如果在也能消费类硬件中运行或训练它们将是其亲民化的巨大进步。我们之前撰写的 LLM.int8 博文 展示了我们是如何将 LLM.int8 论文 中的技术通过 bitsandbytes 库集成到 transformers 中的。在此基础上&#xff0c;我们不断努力以…

怎么学编程效率高,编程练习网站编程软件下载,中文编程开发语言工具下载

怎么学编程效率高&#xff0c;编程练习网站编程软件下载&#xff0c;中文编程开发语言工具下载 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的…

word方框中的对勾如何打?

问题描述&#xff1a;平时在填一些电子版表格时&#xff0c;需要在方框里打对勾&#xff0c;这时如何打呢&#xff1f; 问题解决&#xff1a;符号→其他符号→字体调整为Wingdings 2→找到方框里有对勾的符号&#xff0c;插入即可。 具体如下图所示&#xff1a;

武汉凯迪正大—气体密度继电器校验仪

产品概述 武汉凯迪正大SF6气体密度继电器是用来监测运行中SF6开关本体中SF6气体密度变化的重要元件&#xff0c;其性能的好坏直接影响到SF6开关的运行安全。现场运行的SF6气体密度继电器因不常动作&#xff0c;经过一段时期后常出现动作不灵活、触点接触不良等现象&#xff0c…

Flink架构

1、Apache Flink集群的核心架构&#xff1a; 1、client&#xff08;作业客户端&#xff09;&#xff1a;提交任务的地方叫做客户端 2、JobManager&#xff08;作业管理器&#xff09;&#xff1a;作用是用于管理集群中任务 3、TaskManager&#xff08;任务管理器&#xff09;&a…

wsl2 ubuntu22.04安装docker

1. 安装 docker 官网的步骤一步一步安装即可 Install Docker Engine on Ubuntu | Docker Docs 2. 安装完毕之后&#xff0c;不出意外的话当你运行docker version或者其他命令的时候你会报如下错误&#xff1a; Cannot connect to the Docker daemon at unix:///var/run/docke…