WebSocket 网络通信

导入依赖:

<!-- WebSocket依赖 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>

创建配置类:

package com.mao.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter; /**
* websocket
* 的配置信息
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

创建实现类:

package com.mao.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.apache.commons.lang3.StringUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap; /**
* websocket的处理类。
* 作用相当于HTTP请求
* 中的controller
*/
//@Component
@Slf4j
//@ServerEndpoint("/api/pushMessage/{userId}")
public class WebSocketServer { /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
private static int onlineCount = 0;
/**concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。*/
private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
/**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session;
/**接收userId*/
private String userId = ""; /**
* 连接建立成
* 功调用的方法
*/
@OnOpen
public void onOpen(Session session,@PathParam("userId") String userId) {
this.session = session;
this.userId=userId;
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
//加入set中
webSocketMap.put(userId,this);
}else{
//加入set中
webSocketMap.put(userId,this);
//在线数加1
addOnlineCount();
}
log.info("用户连接:"+userId+",当前在线人数为:" + getOnlineCount());
sendMessage("连接成功");
} /**
* 连接关闭
* 调用的方法
*/
@OnClose
public void onClose() {
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
//从set中删除
subOnlineCount();
}
log.info("用户退出:"+userId+",当前在线人数为:" + getOnlineCount());
} /**
* 收到客户端消
* 息后调用的方法
* @param message
* 客户端发送过来的消息
**/
@OnMessage
public void onMessage(String message, Session session) {
log.info("用户消息:"+userId+",报文:"+message);
System.err.println("session:"+session);
System.err.println("message:"+message);
System.err.println("date:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
} /**
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) { // log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
error.printStackTrace();
} /**
* 实现服务
* 器主动推送
*/
public void sendMessage(String message) {
try {
this.session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
} /**
*发送自定
*义消息
**/
public static void sendInfo(String message, String userId) {
log.info("发送消息到:"+userId+",报文:"+message);
if(StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(message);
}else{
// log.error("用户"+userId+",不在线!");
}
} /**
* 获得此时的
* 在线人数
* @return
*/
public static synchronized int getOnlineCount() {
return onlineCount;
} /**
* 在线人
* 数加1
*/
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
} /**
* 在线人
* 数减1
*/
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
} }

创建测试类:

package com.mao.controller;

import com.mao.pojo.ResponseBean;
import com.mao.pojo.UserInfo;
import com.mao.service.impl.TestServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
@RequestMapping("/api/test")
@Api(value = "服务器向客户端推送消息接口", tags = "Test")
public class TestController { @Autowired
private TestServiceImpl testServiceImpl;
/**
* 启动页面
* @return
*/
@GetMapping("/start")
public String start(){
return "webSoketIndex";
} @PostMapping("/pushToWeb")
@ApiOperation(value = "服务器端向客户端推送消息", notes = "服务器端向客户端推送消息")
public ResponseBean pushToWeb(@RequestBody @ApiParam(value = "回收人编码和医院编码", required = true) UserInfo userInfo){ testServiceImpl.printTime();
return new ResponseBean(200, "success", "123456");
} }

前端测试页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>websocket通讯</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
let socket;
function openSocket() { const socketUrl = "ws://localhost:8080/api/pushMessage/" + $("#userId").val();
console.log(socketUrl);
if(socket!=null){
socket.close();
socket=null;
}
socket = new WebSocket(socketUrl);
//打开事件
socket.onopen = function() {
console.log("websocket已打开");
};
//获得消息事件
socket.onmessage = function(msg) {
console.log(msg.data);
//发现消息进入,开始处理前端触发逻辑
};
//关闭事件
socket.onclose = function() {
console.log("websocket已关闭");
};
//发生了错误事件
socket.onerror = function() {
console.log("websocket发生了错误");
}
}
function sendMessage() { socket.send('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');
console.log('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');
}
</script>
<body>
<p>【socket开启者的ID信息】:<div><input id="userId" name="userId" type="text" value="10"></div>
<p>【客户端向服务器发送的内容】:<div><input id="toUserId" name="toUserId" type="text" value="20">
<input id="contentText" name="contentText" type="text" value="hello websocket"></div>
<p>【操作】:<botton onclick="openSocket()">开启socket</botton>
<p>【操作】:<botton onclick="sendMessage()">发送消息</botton>
<p>【操作】:<botton onclick="">当前用户下线</botton>
</body> </html>

WebSocket网络通信的更多相关文章

  1. 《Cocos2d-x实战 Lua卷》上线了

    感谢大家一直以来的支持!各大商店均开始销售:京东:http://item.jd.com/11659697.html当当:http://product.dangdang.com/23659810.htm ...

  2. swoolefy PHP的异步、并行、高性能网络通信引擎内置了Http/WebSocket服务器端/客户端

    近半年来努力付出,项目终于要正式结项了,团队4人经历了很多困难,加班加点,最终完成了!剩下的时间将总结一下在该项目中用到知识和遇到问题.今天就从swoole说起!项目中实现异步大文件传输的功能,在服务 ...

  3. WebSocket与消息推送

    B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链 ...

  4. HTML5 学习总结(五)——WebSocket与消息推送

    B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链 ...

  5. HTML5 学习笔记(五)——WebSocket与消息推送

    B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链 ...

  6. 【WebSocket初探 】

    众所周知,socket是编写网络通信应用的基本技术,网络数据交换大多直接或间接通过socket进行.对于直接使用socket的client与服务端,一旦连接被建立则均可主动向对方传送数据,而对于使用更 ...

  7. WebSocket学习总结

    一 .websocket 已解决      但是websocket延伸出来的网络编程还有好多知识点没有清理.主要的流程和实现方式已经大概了解清楚,下面从学习的进度思路来一点点复习.        网络 ...

  8. javascript之ProtoBuf在websocket中的使用

    因为ProtoBuf的序列化效率和大小都非常好,所以它在网络通信上面应用越来越多:而webosocket也随着web3.0应用越来越广泛,而将这两个结合在一起的也会慢慢形成一种趋势:本人是为了测试自已 ...

  9. Tornado websocket应用

    应用场景 WebSocket 的特点如下 适合服务器主动推送的场景(好友上线,即时聊天信息,火灾警告,股票涨停等) 相对于Ajax和Long poll等轮询技术,它更高效,不耗费网络带宽和计算资源 它 ...

  10. cocos creator主程入门教程(四)—— 网络通信

    五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 前面已经介绍怎样加载资源.管理弹窗.开发一个网络游戏,难免要处理网络通信.有几点问题需要注意: 1.服务 ...

随机推荐

  1. linux php安装mongodb 扩展

    下载扩展 首先从这个网站选择适合你当前 php 版本的的 mongodb 扩展 https://pecl.php.net/package/mongodb wget https://pecl.php.n ...

  2. 「2024 年度技术精华盘点」IvorySQL & PostgreSQL 技术干货全解析!

    2024 年,IvorySQL 公众号持续输出高质量技术内容,涵盖 PostgreSQL 核心技术解析 和 IvorySQL 创新实践 两大方向.无论您是数据库领域的初学者,还是经验丰富的开发者,这些 ...

  3. K8S组件详解

    K8S的控制平面.和工作节点是集群正常运行的核心,通过这两部分的协同工作,K8S才能够实现高效的容器编排.管理.和自动化运维. K8S Kubernetes(简称K8s),是一个开源的容器编排平台,用 ...

  4. SeaBIOS实现简单分析

    SeaBIOS是一个16bit的x86 BIOS的开源实现,常用于QEMU等仿真器中使用.本文将结合SeaBIOS Execution and code flow和SeaBIOS的源码对SeaBIOS ...

  5. Docker管理面板系列——Portainer

    一.介绍 Portainer是个轻量级的Docker管理面板,和Rancher这种重量级选手没法比,Portainer倾向于单机的管理(后来发现能够添加多个单机节点切换着管理),当然,在Docker搞 ...

  6. 【Linux】U-Boot 加载并启动 Linux 系统程序

    U-Boot 加载并启动 Linux 系统程序 零.介绍 最近在玩一些嵌入式的开发板,在引导操作系统时需要用到U-Boot,故此研究一下. U-Boot(Universal Bootloader)是一 ...

  7. 爆肝 1 周,为我的白板工具支持了 mermaid 流程图,为 ai 生成流程图铺平道路

    朋友们好,前一段时间在博客园推荐了我的白板工具 Drawnix,得到了很多朋友的支持,非常感谢,最近 Drawnix 又有了一些重要更新,其中最实用的应该是支持 mermaid 语法的流程图了. 这是 ...

  8. 剖析 Docker Swarm 操作对容器端口影响

    剖析 Docker Swarm 操作对容器端口影响 一.背景阐述 在使用 Docker Swarm 构建集群环境过程中,于 ts3 节点出现了原有的容器端口全部失效,手动重启后才恢复的情况.期间涉及 ...

  9. 一文搞懂Dockerfile

    Dockerfile官网 https://docs.docker.com/reference/dockerfile/ 什么是Dockerfile? Dockerfile 是一个文本文件,其内包含了一条 ...

  10. Python3 GUI界面

    一.python gui(图形化)模块介绍: Tkinter :是python最简单的图形化模块,总共只有14种组建 Pyqt :是python最复杂也是使用最广泛的图形化 Wx :是python当中 ...