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,并设定一个监听的端口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;
    }
}

 

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

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

相关文章

2023年香港专才计划(输入内地人才计划)拿身份最新申请攻略!

2023年香港专才计划&#xff08;输入内地人才计划&#xff09;拿身份最新申请攻略&#xff01; 近年来&#xff0c;香港受持续的人口老龄化等多因素影响&#xff0c;2022年香港人口总计减少了约12.17万人&#xff0c;跌幅1.6%&#xff0c;其中净移出人数约9.5万人。在此背景下&…

通过创建自定义标签来扩展HTML

使用HTML时&#xff0c;例如&#xff0c;使用<b>标记显示粗体文本。 如果需要列表&#xff0c;则对每个列表项使用<ul>标记及其子标记<li> 。 标签由浏览器解释&#xff0c;并与CSS一起确定网页内容的显示方式以及部分内容的行为。 有时&#xff0c;仅使用一…

Leo赠书活动-06期 【强化学习:原理与Python实战】文末送书

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

频次最高的38道selenium面试题及答案

1、selenium的原理是什么&#xff1f; selenium的原理涉及到3个部分&#xff0c;分别是&#xff1a; 浏览器driver&#xff1a;一般我们都会下载driverclient&#xff1a;也就是我们写的代码 client其实并不知道浏览器是怎么工作的&#xff0c;但是driver知道&#xff0c;在…

Mysql数据库 8.SQL语言 外键约束

一、外键约束 外键约束——将一个列添加外键约束与另一张表的主键&#xff08;唯一列&#xff09;进行关联之后&#xff0c;这个外键约束的列添加的数据必须要在关联的主键字段中存在 案例 创建原则&#xff1a;先创建不含外键的表也就是班级表 添加外键的方式 一般使用第一…

c语言练习10周(11~15)

将b串中的所有字母字符连接在a串之后并输出&#xff0c;a,b串最多30个字符。 题干将b串中的所有字母字符连接在a串之后并输出&#xff0c;a,b串最多30个字符。输入样例abcdef 1A2D3C4F5GG输出样例abcdefADCFGG #include<stdio.h> int main() {char a[30], b[30];int i0…

Java类和对象(1)

&#x1f435;本篇文章将会开始对类和对象的第一部分讲解 一、简单描述类和对象 对象可以理解为一个实体&#xff0c;在现实生活中&#xff0c;比如在创建一个建筑之前&#xff0c;要先有一个蓝图&#xff0c;这个蓝图用来描述这个建筑的各种属性&#xff1b;此时蓝图就是类&a…

如何手动获取spring/springboot中的IOC容器(全局上下文对象)?

IDE&#xff1a;IntelliJ IDEA 2022.2.3 x64 操作系统&#xff1a;win10 x64 位 家庭版 JDK: 1.8 文章目录 前言一、如何手动获取spring容器[ApplicationContext]&#xff1f;方式①&#xff1a;在启动类中获取spring容器方式②&#xff1a;自定义工具类实现ServletContextList…

临界资源,临界区,通信的干扰问题(互斥),信号量(本质,上下文切换问题,原子性,自身的安全性,操作)

目录 引入 概念 临界资源 临界区 干扰存在原因 互斥 信号量 引入 举例 概念 介绍 表示可用资源数 表示等待进程数 申请信号量 信号量的本质 全局变量? 共享内存? 不安全问题 -- 上下文切换 原子性 信号量自身的安全性 原子操作的意义 操作 引入 通信…

Cesium 相机设置

1.setView 直接跳转到目的地 // 设置相机位置 const position Cesium.Cartesian3.fromDegrees(113, 31, 20000); // setView通过定义相机目的地&#xff08;方向&#xff09;,直接跳转到目的地 viewer.camera.setView({ destination: position, // 位置设置 orientation: { //…

适合汽车音频系统的ADAU1977WBCPZ、ADAU1978WBCPZ、ADAU1979WBCPZ四通道 ADC,24-bit,音频

一、ADAU1977WBCPZ 集成诊断功能的四通道ADC&#xff0c;音频 24 b 192k IC&#xff0c;SPI 40LFCSP ADAU1977集成4个高性能模数转换器(ADC)&#xff0c;其直接耦合输入具有10 V rms性能。该ADC采用多位Σ-Δ架构&#xff0c;其连续时间前端能够实现低EMI性能。它可以直接连接…

专业135总分400+西安交通大学信息与通信工程学院909/815考研经验分享

今年初试发挥不错&#xff0c;400&#xff0c;专业课135&#xff0c;将近一年复习一路走来&#xff0c;感慨很多&#xff0c;希望以下经历可以给后来的同学提供一些参考。 初试备考经验 公共课&#xff1a;三门公共课&#xff0c;政治&#xff0c;英语&#xff0c;数学。在备考…

GaN HEMT 电容的分析建模,包括寄生元件

标题&#xff1a;Analytical Modeling of Capacitances for GaN HEMTs, Including Parasitic Components 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;14年&#xff09; 摘要&#xff1a;本文提出了一种基于表面势的终端电荷和电容模型&#xff0c;包…

直接插入排序与希尔排序

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f43b;‍❄个人主页&#x1f389;&#xff1a;GOTXX&#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

4.移位计算,乘除法运算

目录 一. 移位计算 &#xff08;1&#xff09;算数移位 &#xff08;2&#xff09;逻辑移位 &#xff08;3&#xff09;循环移位 二. 乘法运算 &#xff08;1&#xff09;原码的乘法运算 &#xff08;2&#xff09;补码的乘法运算 三. 除法运算 &#xff08;1&#xf…

SpringDataJpa(二)

三、Spring Data JPA概述 Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架&#xff0c;可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能&#xff0c;且易于扩展&#xff01;学习并使用 Spring D…

Python爬虫-获取汽车之家车家号

前言 本文是该专栏的第9篇,后面会持续分享python爬虫案例干货,记得关注。 地址:aHR0cHM6Ly9jaGVqaWFoYW8uYXV0b2hvbWUuY29tLmNuL0F1dGhvcnMjcHZhcmVhaWQ9MjgwODEwNA== 需求:获取汽车之家车家号数据 笔者将在正文中介绍详细的思路以及采集方法,废话不多说,跟着笔者直接往…

GPT-4V:AI在教育领域的应用

OpenAI于9月25日发布了最新的GPT-4V模型&#xff0c;为ChatGPT引入了语音和图像功能&#xff0c;为用户提供更多元化的使用方式。这次更新将为用户带来更便捷、直观的交互体验&#xff0c;用户可以直接拍照上传并针对照片内容提出问题。OpenAI的最终目标是构建安全、有益的人工…

React 其他常用Hooks

1. useImperativeHandle 在react中父组件可以通过forwardRef将ref转发到子组件&#xff1b;子组件拿到父组件创建的ref&#xff0c;绑定到自己的某个元素&#xff1b; forwardRef的做法本身没有什么问题&#xff0c;但是我们是将子组件的DOM直接暴露给了父组件&#xff0c;某下…