SpringBoot(23) 集成socket.io服务端和客户端实现通信
一、前言
websocket
和socket.io
区别?
websocket
- 一种让客户端和服务器之间能进行双向实时通信的技术
- 使用时,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况
- 适合用于client和基于node搭建的服务端使用
socket.io
- 将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口
- 使用时,不用担心兼容问题,底层会自动选用最佳的通信方式
- 适合进行服务端和客户端双向数据通信
w3cschool上对socket.io的描述如下:
本文将实现
- 基于
springboot2.1.8.RELEASE
集成netty-socketio
: 仿node.js
实现的socket.io服务端
- 集成
socket.io-client
:socket.io客户端
- 实现
服务端
与客户端
之间的通信
二、Java
集成socket.io
服务端
1、pom.xml
中引入所需依赖
温馨小提示:这里为了方便将后面需要的客户端
socket.io-client
依赖一起直接引入了哦~
<!-- netty-socketio: 仿`node.js`实现的socket.io服务端 -->
<dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>1.7.7</version>
</dependency>
<!-- socket.io客户端 -->
<dependency><groupId>io.socket</groupId><artifactId>socket.io-client</artifactId><version>1.0.0</version>
</dependency>
2、application.yml
中配置socket.io
服务端
# netty-socketio 配置
socketio:host: 127.0.0.1port: 8888# 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器maxFramePayloadLength: 1048576# 设置http交互最大内容长度maxHttpContentLength: 1048576# socket连接数大小(如只监听一个端口boss线程组为1即可)bossCount: 1workCount: 100allowCustomRequests: true# 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间upgradeTimeout: 1000000# Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件pingTimeout: 6000000# Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔pingInterval: 25000
3、socket.io服务端
配置类
@Configuration
public class SocketIOConfig {@Value("${socketio.host}")private String host;@Value("${socketio.port}")private Integer port;@Value("${socketio.bossCount}")private int bossCount;@Value("${socketio.workCount}")private int workCount;@Value("${socketio.allowCustomRequests}")private boolean allowCustomRequests;@Value("${socketio.upgradeTimeout}")private int upgradeTimeout;@Value("${socketio.pingTimeout}")private int pingTimeout;@Value("${socketio.pingInterval}")private int pingInterval;@Beanpublic SocketIOServer socketIOServer() {SocketConfig socketConfig = new SocketConfig();socketConfig.setTcpNoDelay(true);socketConfig.setSoLinger(0);com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();config.setSocketConfig(socketConfig);config.setHostname(host);config.setPort(port);config.setBossThreads(bossCount);config.setWorkerThreads(workCount);config.setAllowCustomRequests(allowCustomRequests);config.setUpgradeTimeout(upgradeTimeout);config.setPingTimeout(pingTimeout);config.setPingInterval(pingInterval);return new SocketIOServer(config);}}
4、socket.io服务端
服务层
服务类
public interface ISocketIOService {/*** 启动服务*/void start();/*** 停止服务*/void stop();/*** 推送信息给指定客户端** @param userId: 客户端唯一标识* @param msgContent: 消息内容*/void pushMessageToUser(String userId, String msgContent);
}
服务实现类:
@Slf4j
@Service(value = "socketIOService")
public class SocketIOServiceImpl implements ISocketIOService {/*** 存放已连接的客户端*/private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();/*** 自定义事件`push_data_event`,用于服务端与客户端通信*/private static final String PUSH_DATA_EVENT = "push_data_event";@Autowiredprivate SocketIOServer socketIOServer;/*** Spring IoC容器创建之后,在加载SocketIOServiceImpl Bean之后启动*/@PostConstructprivate void autoStartup() {start();}/*** Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题*/@PreDestroyprivate void autoStop() {stop();}@Overridepublic void start() {// 监听客户端连接socketIOServer.addConnectListener(client -> {log.debug("************ 客户端: " + getIpByClient(client) + " 已连接 ************");// 自定义事件`connected` -> 与客户端通信 (也可以使用内置事件,如:Socket.EVENT_CONNECT)client.sendEvent("connected", "你成功连接上了哦...");String userId = getParamsByClient(client);if (userId != null) {clientMap.put(userId, client);}});// 监听客户端断开连接socketIOServer.addDisconnectListener(client -> {String clientIp = getIpByClient(client);log.debug(clientIp + " *********************** " + "客户端已断开连接");String userId = getParamsByClient(client);if (userId != null) {clientMap.remove(userId);client.disconnect();}});// 自定义事件`client_info_event` -> 监听客户端消息socketIOServer.addEventListener(PUSH_DATA_EVENT, String.class, (client, data, ackSender) -> {// 客户端推送`client_info_event`事件时,onData接受数据,这里是string类型的json数据,还可以为Byte[],object其他类型String clientIp = getIpByClient(client);log.debug(clientIp + " ************ 客户端:" + data);});// 启动服务socketIOServer.start();// broadcast: 默认是向所有的socket连接进行广播,但是不包括发送者自身,如果自己也打算接收消息的话,需要给自己单独发送。new Thread(() -> {int i = 0;while (true) {try {// 每3秒发送一次广播消息Thread.sleep(3000);socketIOServer.getBroadcastOperations().sendEvent("myBroadcast", "广播消息 " + DateUtil.now());} catch (InterruptedException e) {e.printStackTrace();}}}).start();}@Overridepublic void stop() {if (socketIOServer != null) {socketIOServer.stop();socketIOServer = null;}}@Overridepublic void pushMessageToUser(String userId, String msgContent) {SocketIOClient client = clientMap.get(userId);if (client != null) {client.sendEvent(PUSH_DATA_EVENT, msgContent);}}/*** 获取客户端url中的userId参数(这里根据个人需求和客户端对应修改即可)** @param client: 客户端* @return: java.lang.String*/private String getParamsByClient(SocketIOClient client) {// 获取客户端url参数(这里的userId是唯一标识)Map<String, List<String>> params = client.getHandshakeData().getUrlParams();List<String> userIdList = params.get("userId");if (!CollectionUtils.isEmpty(userIdList)) {return userIdList.get(0);}return null;}/*** 获取连接的客户端ip地址** @param client: 客户端* @return: java.lang.String*/private String getIpByClient(SocketIOClient client) {String sa = client.getRemoteAddress().toString();String clientIp = sa.substring(1, sa.indexOf(":"));return clientIp;}}
三、Java
开发socket.io
客户端
socket.emit
:发送数据到服务端事件socket.on
: 监听服务端事件
@Slf4j
public class SocketIOClientLaunch {public static void main(String[] args) {// 服务端socket.io连接通信地址String url = "http://127.0.0.1:8888";try {IO.Options options = new IO.Options();options.transports = new String[]{"websocket"};options.reconnectionAttempts = 2;// 失败重连的时间间隔options.reconnectionDelay = 1000;// 连接超时时间(ms)options.timeout = 500;// userId: 唯一标识 传给服务端存储final Socket socket = IO.socket(url + "?userId=1", options);socket.on(Socket.EVENT_CONNECT, args1 -> socket.send("hello..."));// 自定义事件`connected` -> 接收服务端成功连接消息socket.on("connected", objects -> log.debug("服务端:" + objects[0].toString()));// 自定义事件`push_data_event` -> 接收服务端消息socket.on("push_data_event", objects -> log.debug("服务端:" + objects[0].toString()));// 自定义事件`myBroadcast` -> 接收服务端广播消息socket.on("myBroadcast", objects -> log.debug("服务端:" + objects[0].toString()));socket.connect();while (true) {Thread.sleep(3000);// 自定义事件`push_data_event` -> 向服务端发送消息socket.emit("push_data_event", "发送数据 " + DateUtil.now());}} catch (Exception e) {e.printStackTrace();}}}
四、运行测试
当客户端上线后,会通过自定义事件push_data_event
每隔3秒向服务端发送消息,日志如下
而服务端中跑了一个广播消息(自定义事件myBroadcast
) 每隔3秒也会返回给客户端
广播事件
: 向所有的socket连接进行广播发送消息数据
socketIOServer.getBroadcastOperations().sendEvent("myBroadcast", "广播消息 " + DateUtil.now());
日志如下:
编写服务端主动发送消息给客户端接口
@RestController
@RequestMapping("/api/socket.io")
@Api(tags = "SocketIO测试-接口")
public class SocketIOController {@Autowiredprivate ISocketIOService socketIOService;@PostMapping(value = "/pushMessageToUser", produces = Constants.CONTENT_TYPE)@ApiOperation(value = "推送信息给指定客户端", httpMethod = "POST", response = ApiResult.class)public ApiResult pushMessageToUser(@RequestParam String userId, @RequestParam String msgContent) {socketIOService.pushMessageToUser(userId, msgContent);return ApiResult.ok();}}
调用接口测试发送helloworld…
五、总结
socket.io通信,服务端:
1.socketIOServer.addConnectListener
:监听客户端连接
2. socketIOServer.addDisconnectListener
:监听客户端断开连接
3. socketIOServer.addEventListener
:监听客户端传输的消息
4. client.sendEvent("自定义事件名称", "消息内容")
:服务端向指定的clien客户端发送消息
5. socketIOServer.getBroadcastOperations().sendEvent("自定义事件名称", "消息内容")
:服务端发送广播消息给所有客户端
socket.io通信,客户端:
IO.socket(url)
:与指定的socket.io服务端建立连接socket.emit
:发送数据到服务端事件socket.on
: 监听服务端事件
本文案例demo源码
https://gitee.com/zhengqingya/java-workspace
SpringBoot(23) 集成socket.io服务端和客户端实现通信相关推荐
- socket.io服务端是java_SpringBoot(23) 集成socket.io服务端和客户端实现通信
@Slf4j @Service(value = "socketIOService") public class SocketIOServiceImpl implements ISo ...
- 2-3 建立简易TCP服务端、客户端【socket server/client】【socket、bind、listen、accept、send、closesocket】【conect、recv】
2-3 建立简易TCP服务端.客户端 文章目录 2-3 建立简易TCP服务端.客户端 0-前言 1-服务端简易功能 2-客户端简易功能 3-代码逻辑 4-服务端 4-1 建立socket 4-2 绑定 ...
- Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信
本文计划采用socket实现客户端和服务端的任意双向通信,即客户端可以随时给服务端发消息,服务端也可以随时给客户端发消息,最终结果就是一个类似与QQ的聊天软件的功能. 以下代码可以直接拷贝到Eclip ...
- Java中利用socket实现简单的服务端与客户端的通信(基础级)
在上一篇文章中,简单的介绍了java中入门级的socket编程,简单的实现了客户端像服务器端发送数据,服务器端将数据接收并显示在控制台,没有涉及多线程.上一篇文章的链接:Java中利用socket实现 ...
- Java中利用socket实现简单的服务端与客户端的通信(入门级)
Java编程中,要想要使用网络通信,就离不开Socket编程,在此对socket进行简单的介绍.首先声明,这是一个入门级的介绍,仅仅简单的实现了客户端向服务端发送数据,服务端正常的接收数据,当接收到特 ...
- SpringBoot使用Mina框架进行服务端与客户端数据通信
pom.xml引入 <dependency><groupId>org.apache.mina</groupId><artifactId>mina-cor ...
- java 集成 cas系统 服务端和客户端配置
http://blog.csdn.net/yunye114105/article/details/7997041 参考: http://blog.csdn.net/diyagea/article/de ...
- Java实现服务端和客户端的通信(文件下载)
网络编程 网络通信的介绍 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据 两台电脑连在一起就组成了一个计算机网络.我们通过光纤连接到电信的网关,中国电信通过海底光缆和美国电信网关连接,你 ...
- 使用WebSocket实现服务端和客户端的通信
开发中经常会有这样的使用场景.如某个用户在一个数据上做了xx操作, 与该数据相关的用户在线上的话,需要实时接收到一条信息. 这种可以使用WebSocket来实现. 另外,对于消息,可以定义一个类进行固 ...
最新文章
- 如何制作风格迁移图?
- ASP.NET Razor – C# 变量简介
- Nodejs介绍及其安装
- VTK:可视化算法之PineRootDecimation
- html5时间画布走动,javascript+HTML5 canvas绘制时钟功能示例
- python 对axis的理解
- 【MSDN文摘】使用自定义验证组件库扩展 Windows 窗体: Form Scope
- shell如何解决mysql交互式_shell脚本与mysql交互方法汇总
- CentOS 安装MySQL(rpm)提示错误Header V3 DSA/SHA1 Signature
- Android仿华为天气绘制刻度盘
- 2015年10月26日作业
- 手机不能访问html文件,手机如何解决禁止访问网页
- 数据挖掘经典算法--priori算法
- 智能型电话远程遥控器
- 腾讯云主机配置tomcat服务器
- dumb-init:一个Docker容器初始化系统
- python控制小爱同学_神秘鸭,用Siri小爱同学语音助手控制你的电脑
- 从实战经验来看 究竟如何才能做出赚钱的量化投资策略?
- 项目管理必备工具——甘特图
- ActiveX控件之制作图片属性页
热门文章
- 我国SM9密钥交换协议正式成为ISO/IEO国际标准,SM9算法全系完成国际标准认证
- vue中使用moment处理时间戳转换成日期或时间格式
- 2019年公务员计算机(大类)类,2019年国家公务员考试证监会参公事业单位计算机类大纲...
- js之深浅克隆(深浅拷贝)
- 关闭shift中英文切换 英文代码/中文注释随意切换着写。
- 用CocosCreator来做一个黄金矿工吧(二)
- 双目立体匹配:AD Census
- Revit(8)-数据结构-类别、族概念
- 利用Stram来递归生成树形结构
- centos下一键安装lamp环境,快捷,方便