项目情境:

   有一个第三方的网络键盘(键盘按键连接后会发送指令)配置到项目上,实现键盘按键,发送的指令经服务层接收封装后发送给各个业务线,实现键盘的交互。

解决思路:

  因为交互是持久的,键盘操作命令是断断续续的,所以采用socket的长链接模式,与以往不同,此次java服务层作为socket的客户端主动去连接键盘,并与键盘实现心跳连接,接收发命令,根据键盘配置的手册,实现整个交互。

编码示例:

1.连接服务线程

package com.jovision.mix.keyboard.service.socket.server;import java.net.InetAddress;
import java.net.Socket;/*** TCP Socket客户端*          用来连接网络键盘* @author sww* @since 2021/11/8*/
public abstract class TcpClient implements Runnable {private int port;private String hostIP;private boolean connect = false;private SocketTransceiver transceiver;/*** 建立连接* <p>* 连接的建立将在新线程中进行* <p>* 连接建立成功,回调{@code onConnect()}* <p>* 连接建立失败,回调{@code onConnectFailed()}* * @param hostIP*            服务器主机IP* @param port*            端口*/public void connect(String hostIP, int port) {this.hostIP = hostIP;this.port = port;new Thread(this).start();}@Overridepublic void run() {try {Socket socket = new Socket(hostIP, port);//socket.setKeepAlive(true);transceiver = new SocketTransceiver(socket) {@Overridepublic void onReceive(InetAddress addr, String s) {TcpClient.this.onReceive(this, s);}@Overridepublic void onDisconnect(InetAddress addr) {connect = false;TcpClient.this.onDisconnect(this);}};transceiver.start();connect = true;this.onConnect(transceiver);} catch (Exception e) {e.printStackTrace();this.onConnectFailed(transceiver);}}/*** 断开连接* <p>* 连接断开,回调{@code onDisconnect()}*/public void disconnect() {if (transceiver != null) {transceiver.stop();transceiver = null;}}/*** 判断是否连接* * @return 当前处于连接状态,则返回true*/public boolean isConnected() {return connect;}/*** 获取Socket收发器* * @return 未连接则返回null*/public SocketTransceiver getTransceiver() {return isConnected() ? transceiver : null;}/*** 连接建立* * @param transceiver*            SocketTransceiver对象*/public abstract void onConnect(SocketTransceiver transceiver);/*** 连接建立失败*/public abstract void onConnectFailed(SocketTransceiver transceiver);/*** 接收到数据* <p>* 注意:此回调是在新线程中执行的* * @param transceiver*            SocketTransceiver对象* @param s*            字符串*/public abstract void onReceive(SocketTransceiver transceiver, String s);/*** 连接断开* <p>* 注意:此回调是在新线程中执行的* * @param transceiver*            SocketTransceiver对象*/public abstract void onDisconnect(SocketTransceiver transceiver);
}

2.接收发线程:

package com.jovision.mix.keyboard.service.socket.server;import lombok.extern.slf4j.Slf4j;import java.io.*;
import java.net.InetAddress;
import java.net.Socket;/*** Socket收发器 通过Socket发送数据,并使用新线程监听Socket接收到的数据* 处理消息** @author * @since 2021/11/8*/
@Slf4j
public abstract class SocketTransceiver implements Runnable {protected Socket socket;protected InetAddress addr;protected DataInputStream in;protected DataOutputStream out;private boolean runFlag;/*** 实例化** @param socket 已经建立连接的socket*/public SocketTransceiver(Socket socket) {this.socket = socket;this.addr = socket.getInetAddress();}/*** 获取连接到的Socket地址** @return InetAddress对象*/public InetAddress getInetAddress() {return addr;}/*** 开启Socket收发* <p>* 如果开启失败,会断开连接并回调{@code onDisconnect()}*/public void start() {runFlag = true;new Thread(this).start();}/*** 断开连接(主动)* <p>* 连接断开后,会回调{@code onDisconnect()}*/public void stop() {runFlag = false;try {socket.shutdownInput();in.close();} catch (Exception e) {e.printStackTrace();}}/*** 发送字符串** @param* @return 发送成功返回true*/public boolean send(String data) {if (out != null) {try {// 使用gb2312编码out.write(data.getBytes("gb2312"));out.flush();return true;} catch (Exception e) {e.printStackTrace();}}return false;}/*** 监听Socket接收的数据(新线程中运行)*/@Overridepublic void run() {try {in = new DataInputStream(this.socket.getInputStream());out = new DataOutputStream(this.socket.getOutputStream());} catch (IOException e) {e.printStackTrace();runFlag = false;}while (runFlag) {try {byte[] bys = new byte[100];int byteread = 0;while ((byteread = in.read(bys)) != -1) {String str = new String(bys, 0, byteread);System.out.println("获取到键盘输入的信息为" + str);this.onReceive(addr, str);}} catch (IOException e) {// 连接被断开(被动)runFlag = false;}}// 断开连接try {log.info("执行清空消息步骤");in.close();out.close();socket.close();in = null;out = null;socket = null;} catch (IOException e) {e.printStackTrace();}this.onDisconnect(addr);}/*** 接收到数据* <p>* 注意:此回调是在新线程中执行的** @param addr 连接到的Socket地址* @param s    收到的字符串*/public abstract void onReceive(InetAddress addr, String s);/*** 连接断开* <p>* 注意:此回调是在新线程中执行的** @param addr 连接到的Socket地址*/public abstract void onDisconnect(InetAddress addr);
}

主要代码如上,一个用来连接服务线程,一个作为接收处理消息线程,再单独写一个整合两个线程的类方法,重写方法。
因为是服务端主动连接键盘,所以封装好的方法被调用时是异步的,本次使用了spring的消息发布监听模式。

@Slf4j
@Component
public class KeyBoardApplicationListener implements ApplicationListener<KeyBoardApplicationEvent> {//1.页面配置ip和端口号后 发送事件 把IP和端口号 发送到监听器//2、监听器接收到 ip和端口号后建立连接 如果成功 修改数据库@Autowiredprivate ConnectKeyboardServer connectKeyboardServer;@Autowiredprivate NetworkKeyboardService networkKeyboardService;@Async@Overridepublic void onApplicationEvent(KeyBoardApplicationEvent keyBoardApplicationEvent) {//接收客户端请求String ip = keyBoardApplicationEvent.getIp();Integer port = keyBoardApplicationEvent.getPort();log.info("监听到网络键盘上线请求;ip:{},端口:{}",ip,port);//如何维护这些端口和IP//1.建立连接 接收请求和发送请求ReconnectBo reconnectBo=new ReconnectBo();reconnectBo.setIp(ip);reconnectBo.setPort(port);// 查看当前键盘是否离线 在线不进行操作Integer status=networkKeyboardService.queryNetworkStatus(reconnectBo);log.info("键盘在线状态为:{}",status);if (status==1){log.info("键盘离线======开启网络键盘连接");connectKeyboardServer.connectionKeyBoard(reconnectBo);}else{log.info("键盘在线======不允许进行连接");}}
}

java使用 Socket 作为客户端连接网络键盘 实操相关推荐

  1. socket多客户端连接服务器

    socket多客户端连接服务器     关于套接字编程,我们可以使用它来完成网络通信,而关于使用socket来实现多客户端连接服务器,我记录了以下东西.     一.基本思路        1.服务器 ...

  2. Java网络爬虫实操(5)

    上一篇:Java网络爬虫实操(4) 大家好,前几篇文章介绍的URL都是返回HTML内容的,然后再从HTML字符串里解析出我们想要的数据. 但是,随着前端编程技术的发展,至少十多年前开始ajax.jso ...

  3. Java网络爬虫实操(3)

    上一篇:Java网络爬虫实操(2) 本篇文章主要介绍NetDiscovery框架中pipeline模式的一些实际使用方法. 1) 什么是pipeline pipeline是一种常见的算法模式,针对不断 ...

  4. Java网络爬虫实操(8)

    上一篇:Java网络爬虫实操(7) 大家好,本篇文章介绍一下NetDiscovery爬虫框架里的downloader对象 1) 前言 面向对象设计仍然是目前编程的核心思想,从下面截图可以了解爬虫框架的 ...

  5. python实现socket多客户端连接

    socket实现同网络下不同机器之间互联,常规写法,直接创建后只能有一个客户端连接到服务端,无法实现多客户端连接.在这里使用多线程的方法创建多个监听来实现多客户端连接同一个服务端. server端代码 ...

  6. MySQL客户端连接网络不稳定解决办法

    博文背景 作者是中国移动的校园网,网络连接不是很稳定,连接远程MySQL服务器会经常性出现断连现象,所以导致每次只要在客户端等几分钟不操作后再去执行操作时会导致需要新的新的连接建立需要十几秒中,大大降 ...

  7. java客户端运行hadoop_JAVA客户端连接部署在docker上的hdfs

    docker上已经成功部署了hdfs应用,jps命令也显示了namenode和datanode启动正常.浏览器显示 宿主机ip:50070 页面 我在eclipse使用java连接hdfs,代码如下: ...

  8. java网络爬虫实验报告,Java网络爬虫实操(8)

    大家好,本篇文章介绍一下NetDiscovery爬虫框架里的downloader对象 1) 前言 面向对象设计仍然是目前编程的核心思想,从下面截图可以了解爬虫框架的主要对象: 程序在本地组织好一个re ...

  9. java spider爬虫_Java网络爬虫实操(2)

    本篇文章继续介绍爬虫框架NetDiscovery的使用:如何发重复请求.如何用爬虫容器引擎驱动爬虫程序 1 )重复请求的场景举例 从2017年下半年开始,比特币.数字货币.虚拟币.区块链技术.去中心化 ...

最新文章

  1. redis基本命令list
  2. 焊接件技术要求怎么写_专硕论文写作要求有高么?具体怎么写?
  3. 2020 ccf推荐中文期刊_CCF推荐国际学术期刊
  4. [js]jquery里的jsonp实现ajax异源请求
  5. 无服务器架构_如何开始使用无服务器架构
  6. php 分割二维数组,拆分二维数组 php
  7. php电商网站开发流程图,php网上购物平台设计+ER图+流程图.doc
  8. 面试—每日一题(6)
  9. 11年写的一篇文章----智能终端安全现状及前景展望
  10. 《构建之法》第四章读后感--软件工程
  11. 1 Spark机器学习 spark MLlib 入门
  12. Kali扫描工具Nmap
  13. 互联网周刊封面文章:全球网络广告三大趋势
  14. .NET之盛派微信SDK简单操作
  15. c语言寻找因数,【代码】求一个数的因数和、求优化、顺便也供新人参考算法...
  16. MindManager2020官方中文版思维导图软件使用激活安装免费教程下载
  17. GNN、GCN、GAT关系
  18. 视觉机器人+人体姿态识别项目总结
  19. idea打开maven项目时,部分jar包报红问题
  20. 主板BIOSCOMS故障解决三例

热门文章

  1. mindManager中修改主题,便签、便笺的背景
  2. window 便笺的快捷键
  3. 什么是计算机用英语解释,常用计算机英语解释
  4. 基于ssm商城系统源码springboot商城系统源码
  5. java字符串转数字,各种数字转字符串的3种方法
  6. 如何隐藏网络计算机,电脑隐藏wifi怎么设置_电脑如何设置隐藏wifi?-192路由网...
  7. 2019年前端常见jQuery面试题
  8. 计算机信息安保ppt,安保系统ppt精选.ppt
  9. kafka技术内幕 pdf 下载_现代实用气动技术 第2版 pdf下载 0776
  10. Chrome浏览器关闭自动更新