Java UDP Socket 实时在线刷卡扫码POS消费机服务端示例源码
本示例使用的设备:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.52de2c1bYG0BuO&ft=t&id=17021194999
一、获取本电脑所有网卡IP
public static String getIP() {Enumeration<NetworkInterface> netInterfaces;ArrayList<String> IpAddList = new ArrayList<String>();try {netInterfaces = NetworkInterface.getNetworkInterfaces(); // 拿到所有网卡InetAddress ip;while (netInterfaces.hasMoreElements()) {NetworkInterface ni = netInterfaces.nextElement();Enumeration<InetAddress> addresses = ni.getInetAddresses();while (addresses.hasMoreElements()) {ip = addresses.nextElement();if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf(':') == -1) {IpAddList.add(ip.getHostAddress());System.out.println((IpAddList.size() - 1) + "" + " " + ni.getName() + " " + ip.getHostAddress());}}}} catch (Exception e) {}if (IpAddList.isEmpty()) {return "127.0.0.1";} else {return IpAddList.get(0); //如有多张网卡,请选择与设备相连的网卡,否则无法与设备正常通讯}
}
二、服务端开启UDP端口接收消费机提交的请求
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;public class Main {public static void main(String[] args) throws Exception{String MyIpAdd=getIP(); //获取电脑网卡IPint MyPort=39192; //监听端口 InetAddress Addip=InetAddress.getByName(MyIpAdd) ;DatagramSocket s = new DatagramSocket(MyPort); /** 1、建立udp socket端点 */System.out.println("当前系统绑定的网卡:"+MyIpAdd+":"+String.format("%d",MyPort));while(true){byte [] bbuf = new byte [1024]; /**2、预先创建接收数据存放的位置,封装*/DatagramPacket rdp = new DatagramPacket(bbuf,bbuf.length);s.receive(rdp); /**3、使用receive阻塞式接收*/String ReceiveDataStr=new String(rdp.getData());String RemoteHostIP=rdp.getAddress().getHostAddress();int RemotePort=rdp.getPort();System.out.println("From ip::"+rdp.getAddress().getHostAddress()+"\nport::"+rdp.getPort()+"\ndata::"+ReceiveDataStr+"\n\n");String[] strArr = ReceiveDataStr.split("\\,"); /*分割接收到的数据后再分析、处理、返回指令 */}}
}
三、接收到消费机上传的刷卡数据
if (strArr[0].equals("102")){ /*接收到直接刷卡的信息*/DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferCardidStr = strArr[5]; /*卡号*/if(strArr.length>6){ /*2018年以后的设备有唯一硬件序号*/DevBufferSerialNumStr=strArr[6];}SendInfStr="001,"+DevRecFramesStr; /*向设备发此数据表示已收到信息,否则设备会连续发三次*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);/*此处加入业务对数据库的查、增、删、减操作*//*009指令返回持卡人信息*/SendInfStr="009," + DevBufferMachinStr + ",卡号:" + DevBufferCardidStr + "\\n姓名:张三丰\\n余额:888.88\\n状态:卡可正常使用\\n,20,1,0" ;SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);
}
四、接收到消费机上传的现金支付请求
if (strArr[0].equals("103")){ /*接收到 输入消费金额后刷卡、消费机定额消费、消费机计次消费 的上传信息 */DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferCardidStr = strArr[5]; /*卡号*/DevBufferUseMoneryStr= strArr[6]; /*消费金额*/DevBufferUseTimeStr= strArr[7]; /*消费时间*/if(strArr.length>8){ /*2018年以后的设备有唯一硬件序号*/DevBufferSerialNumStr=strArr[8];}SendInfStr="001,"+DevRecFramesStr; /*向设备发此数据表示已收到信息,否则设备会连续发三次*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);/*此处加入业务对数据库的查、增、删、减操作*//*008指令返回本次消费成功,006指令返回本次消费失败,正式系统开发时要有重发机制*/SendInfStr="008," + DevBufferMachinStr + "," + DevBufferCardidStr+ ","+DevBufferUseMoneryStr+"," + "姓名:张三丰 {123.45}\\n,20,0,1" ;SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);
}
五、接收到消费机上传的计次消费请求
if (strArr[0].equals("104")){ /*接收到 计次消费模式下,终端刷卡后设备向电脑发送此信息 */DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferCardidStr = strArr[5]; /*卡号*/DevBufferUseTimeStr= strArr[6]; /*消费时间*/if(strArr.length>7){ /*2018年以后的设备有唯一硬件序号*/DevBufferSerialNumStr=strArr[7];}SendInfStr="001,"+DevRecFramesStr; /*向设备发此数据表示已收到信息,否则设备会连续发三次*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);/*此处加入业务对数据库的查、增、删、减操作*//*008指令返回本次消费成功,006指令返回本次消费失败,正式系统开发时要有重发机制*/SendInfStr="006," + DevBufferMachinStr + "," + DevBufferCardidStr+ "," + "姓名:张三丰 \\n余额:123.45\\n状态:累计次数超出\\n,20,0,14" ;SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);
}
六、接收到消费机上传的记账消费记录
if (strArr[0].equals("105")){ /*接收到 脱网记账消费记录,消费机开启记账功能,有脱机记账消费记录网络恢复正常自动向电脑发送此信息 */DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferCardidStr = strArr[5]; /*卡号*/DevBufferUseMoneryStr= strArr[6]; /*消费金额*/DevBufferUseTimeStr= strArr[7]; /*消费时间*/DevBufferStaryStr= strArr[8]; /*消费方式 0扣费 1计次*/DevBufferRecordAddStr= strArr[9]; /*记录地址标识*/DevBufferAllNoStr= strArr[10]; /*总计录数*/if(strArr.length>11){ /*2018年以后的设备有唯一硬件序号*/DevBufferSerialNumStr=strArr[11];}SendInfStr="001,"+DevRecFramesStr; /*向设备发此数据表示已收到信息,否则设备会连续发三次*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);if(!IsDateTime(DevBufferUseTimeStr)){ /*判断消费时间是否正确*/DevBufferUseTimeStr= "9999-99-99 99:99:99"; /*如果消费时间不正确,需更为 9999-99-99 99:99:99 才能将此条记录删除 */}/*清除设备内当前这条已上传的记录,驱动设备继续上传剩下的记录*/SendInfStr="011," + DevBufferMachinStr + "," + DevBufferCardidStr + "," + DevBufferUseMoneryStr + "," + DevBufferUseTimeStr + "," + DevBufferRecordAddStr;SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort); 执行此指令将清除消费机内当前已上传的记录,清除后消费机继续将后一条记录上传,直到全部记㥆上传完毕
}
七、接收到消费机上传的按键信息
if (strArr[0].equals("106")){ /*接收到设备的按键信息*/DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferInputKeyStr= strArr[5]; /*按键信息*/if(strArr.length>6){ /*2018年以后的设备有唯一硬件序号*/DevBufferSerialNumStr=strArr[6];}SendInfStr="001,"+DevRecFramesStr; /*向设备发此数据表示已收到信息,否则设备会连续发三次*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);
}
八、接收到消费机上传的扫码支付请求
if (strArr[0].equals("128")){ /*接收到消费金额及扫码信息*/DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferCommandStr = strArr[5]; /*口令*/DevBufferUseMoneryStr= strArr[6]; /*消费金额*/DevBufferUseTimeStr= strArr[7]; /*消费时间*/DevBufferQrcodeInfStr="";if(strArr.length>9){ //防止二维码信息中有分隔符,for(j=9;j<strArr.length-1;j++){DevBufferQrcodeInfStr=DevBufferQrcodeInfStr+strArr[j];}DevBufferQrcodeInfStr=DevBufferQrcodeInfStr.trim();DevBufferSerialNumStr=strArr[strArr.length-1]; /*2018年以后的设备有唯一硬件序号*/}SendInfStr="001,"+DevRecFramesStr; /*向设备发此数据表示已收到信息,否则设备会连续发三次*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);/*此处加入业务对数据库的查、增、删、减操作*//*008指令返回本次消费成功,006指令返回本次消费失败,正式系统开发时要有重发机制*/SendInfStr="008," + DevBufferMachinStr + "," + DevBufferCommandStr+ ","+DevBufferUseMoneryStr+"," + "正在进行扫码支付..{请不要按动键盘! \n},5,0,1" ;SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);
}
九、接收到消费机开机信号
if (strArr[0].equals("101")){ /*有设备开机的信号*/DevRecFramesStr = strArr[1]; /*包序列号 */DevBufferIpAddrStr = strArr[2]; /*终端IP */DevBufferRemoteAddrStr = strArr[3]; /*远程电脑指机IP*/DevBufferMachinStr = strArr[4]; /*机号*/DevBufferDatetimeStr = strArr[5]; /*日期时间*/if(strArr.length>6){ /*2018年以后的设备有唯一硬件序号*/DevBufferSerialNumStr=strArr[6];}String SysNowTime=GetSysDT(); /*取系统时间*/if(DevBufferDatetimeStr.substring(0,16).compareTo(SysNowTime.substring(0,16))!=0){SendInfStr="003,"+DevBufferMachinStr+","+SysNowTime; /*设备时钟与系统不符,更新设备时间*/SendInfToDiv(s,SendInfStr,RemoteHostIP,RemotePort);}
}
十、服务端回应消费机的指令
static void SendInfToDiv(DatagramSocket s,String Sendinf,String RemoIp,int RemoPro) throws Exception{byte[] SendBuf = Sendinf.getBytes("gb2312"); /** 发送数据,封装打包 */DatagramPacket dp1 = new DatagramPacket(SendBuf, SendBuf.length, InetAddress.getByName(RemoIp), RemoPro);try {s.send(dp1);System.out.println("SendTo ip::"+RemoIp+"\nport::"+String.valueOf(RemoPro)+"\ndata::"+Sendinf+"\n\n");} catch (IOException e) {System.out.println("发送失败: ");e.printStackTrace();}
}