WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

http协议是单向通信,一般由客户端发起请求,然后接收服务端响应。如果要实现客户端实时消息跟新功能如:更新聊天消息,更新邮件信息,更新后台系统员工待办事消息等,传统的做法是基于http协议,然后客户端定时轮询(如每秒访问一次)访问服务端,但是这样就会产生大量无效的http请求,浪费了服务器资源。

而 WebSocket ,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输,客户端可以向服务端发送通信,并且客户端不必轮询请求服务端,服务端如果有消息可以直接发送给客户端。

以下是WebSocket实现聊天室代码示例:

1.集成webSocket

maven添加

<dependency>      <groupId>org.springframework.bootgroupId>      <artifactId>spring-boot-starter-websocketartifactId>  dependency>

添加配置类:WebSocketConfig

@Configurationpublic class WebSocketConfig {    @Bean    public ServerEndpointExporter serverEndpointExporter(){        return new ServerEndpointExporter();    }}

2.开发WebSocket服务端:

//@ServerEndpoint("/imserver/{userId}") 、@Component即可启用//WebSocket服务//@OnOpen开启连接触发调用,@onClose关闭连接触发调用//,@onMessage接收消息触发掉用@ServerEndpoint("/imserver/{userId}")@Componentpublic class WebSocketServer {    /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/    private static int onlineCount = 0;    //缓存每个客户端对应的MyWebSocket对象。    //如果是集群可改成redis或mysql    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);            webSocketMap.put(userId,this);        }else{            //如果新连接存入缓存中            webSocketMap.put(userId,this);            //在线人数加  1            addOnlineCount();        }        try {            //向链接客户端发送链接成功消息            sendMessage("{\"contentText\":\"连接成功\"}");            //跟新连接上的用户的在线人数            if(onlineCount > 0){                webSocketMap.values().forEach(x -> {                    try {                        x.sendMessage("{\"onlineCount\":"+onlineCount+"}");                    } catch (IOException e) {                    }                });            }        } catch (IOException e) {        }    }    /**     * 连接关闭调用的方法     */    @OnClose    public void onClose() {        if(webSocketMap.containsKey(userId)){            //从缓存中移除断开的链接            webSocketMap.remove(userId);            //在线人数  - 1            subOnlineCount();            //跟新连接上的用户的在线人数            if(onlineCount > 0){                webSocketMap.values().forEach(x -> {                    try {                        x.sendMessage("{\"onlineCount\":"+onlineCount+"}");                    } catch (IOException e) {                        e.printStackTrace();                    }                });            }        }    }    /**     * 收到客户端消息后调用的方法     *     * @param message 客户端发送过来的消息*/    @OnMessage    public void onMessage(String message, Session session) {        //可以群发消息        //消息保存到数据库、redis        if(!StringUtils.isEmpty(message)){            try {                //解析发送的报文                JSONObject jsonObject = JSON.parseObject(message);                //追加发送人(防止串改)                jsonObject.put("fromUserId",this.userId);                String toUserId=jsonObject.getString("toUserId");                //传送给对应toUserId用户的websocket                if((!StringUtils.isEmpty(toUserId))&&webSocketMap.containsKey(toUserId)){                    //向客户端发送消息                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());                }else{                    //否则不在这个服务器上,发送到mysql或者redis                }            }catch (Exception e){                e.printStackTrace();            }        }    }    /**     *     * @param session     * @param error     */    @OnError    public void onError(Session session, Throwable error) {        error.printStackTrace();    }    /**     * 实现服务器主动推送     */    public void sendMessage(String message) throws IOException {        this.session.getBasicRemote().sendText(message);    }    /**     * 发送自定义消息     * */    public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {        if((!StringUtils.isEmpty(userId))&&webSocketMap.containsKey(userId)){            webSocketMap.get(userId).sendMessage(message);        }else{        }    }    public static synchronized int getOnlineCount() {        return onlineCount;    }    public static synchronized void addOnlineCount() {        WebSocketServer.onlineCount++;    }    public static synchronized void subOnlineCount() {        WebSocketServer.onlineCount--;    }}

3.客户端WebSocket开发

目前 HTML5 以支持WebSocket

var Socket = new WebSocket(url, [protocol] );WebSocket相关事件:open  Socket.onopen  连接建立时触发message  Socket.onmessage  客户端接收服务端数据时触发error  Socket.onerror  通信发生错误时触发close  Socket.onclose  连接关闭时触发
<html><head>    <meta charset="utf-8">    <title>websocket通讯title>head><script src="./jquery-1.7.2.js">script><script>    var socket;    function openSocket() {        if(typeof(WebSocket) == "undefined") {            console.log("您的浏览器不支持WebSocket");        }else{            console.log("您的浏览器支持WebSocket");            //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接            //等同于socket = new WebSocket("ws://localhost:8888/xxxx/im/25");            //var socketUrl="${request.contextPath}/im/"+$("#userId").val();            var socketUrl="http://localhost:9999/imserver/"+$("#userId").val();            socketUrl=socketUrl.replace("https","ws").replace("http","ws");            console.log(socketUrl);            if(socket!=null){                socket.close();                socket=null;            }            socket = new WebSocket(socketUrl);            //打开事件            socket.onopen = function() {                console.log("websocket已打开");                //socket.send("这是来自客户端的消息" + location.href + new Date());            };            //获得消息事件            socket.onmessage = function(msg) {                console.log(msg.data);                //发现消息进入    开始处理前端触发逻辑                $("#contentText").val($.parseJSON(msg.data).contentText);                $("#onlineCount").val($.parseJSON(msg.data).onlineCount);            };            //关闭事件            socket.onclose = function() {                console.log("websocket已关闭");            };            //发生了错误事件            socket.onerror = function() {                console.log("websocket发生了错误");            }        }    }    function sendMessage() {        if(typeof(WebSocket) == "undefined") {            console.log("您的浏览器不支持WebSocket");        }else {            console.log("您的浏览器支持WebSocket");            var inputText = $("#inputText").val();            console.log('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+inputText+'"}');            socket.send('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+inputText+'"}');        }    }script><body><p>【在线人数】:<div><input id="onlineCount" name="onlineCount" type="text" >div><p>【userId】:<div><input id="userId" name="userId" type="text" value="10">div><p>【toUserId】:<div><input id="toUserId" name="toUserId" type="text" value="20">div><p>【message】:<div>                <textarea id="contentText" name="contentText" type="text" value="hello websocket">textarea>                div><p>【input】:<div><input id="inputText" name="inputText" type="text" >div><p>【操作】:<div><a onclick="openSocket()">开启socketa>div><p>【操作】:<div><a onclick="sendMessage()">发送消息a>div>body>html>

4.演示:

      

websocket多客户端接收消息_WebSocket之消息接收发送相关推荐

  1. ios个推透传消息json接收不到_消息通讯——Websocket

    说起即时通讯大家应该都听过,像各种聊天软件用到的即时通讯技术是最多的.另外开发过程中实现消息推送最传统的做法就是轮询,即按照特定时间间隔由浏览器对服务器发送请求,以获取最新消息,这种传统模式带来很明显 ...

  2. python3.6 websocket异步高并发_在Python3.6上的websocket客户端中侦听传入消息时出现问题...

    我正在尝试使用websockets包在Python上构建一个websockets客户端:Websockets 4.0 API 我使用这种方式而不是示例代码,因为我想创建一个websocket客户机类对 ...

  3. 客户端关闭服务器收到消息推送消息,【网络编程】——WebSocket打开和关闭通道,消息发送...

    HTML5给Web浏览器带来了全双工TCP链接WebSocket标准服务器的能力.浏览器和可以与服务器创建链接,经过已创建的通讯信道来发送和接收数据而不须要由HTTP协议入额外的开销.javascri ...

  4. 未能分析从服务器收到的消息,WebSocket Javascript客户端未收到来自服务器的消息...

    我已经在本地GlassFish 4.1服务器上部署了Java Web应用程序,该服务器实现了与Web客户端互操作的WebSockets.我能够通过套接字成功执行客户端到服务器的通信,但由于某种原因,服 ...

  5. C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密

    在上篇随笔<C#开发微信门户及应用(19)-微信企业号的消息发送(文本.图片.文件.语音.视频.图文消息等)>介绍了有关企业号的消息发送,官方特别声明消息是不用加密发送的.但是在回调的服务 ...

  6. 公众号 接收规则 消息_微信公众平台 发送模板消息(Java接口开发)

    前言:最近一直再弄微信扫码推送图文消息和模板消息发送,感觉学习到了不少东西.今天先总结一下微信公众平台模板消息的发送.因为这个自己弄了很久,开始很多地方不明白,所以今天好好总结一下. 微信公众平台技术 ...

  7. 通过websocket抓取斗鱼弹幕和礼物消息

    1.斗鱼弹幕协议 到斗鱼官方开放平台看斗鱼通讯协议,网址"斗鱼开放平台",登录后可查看 所以根据斗鱼协议做编码函数: 1 def msg_encode(msg):2 #消息以 \0 ...

  8. 【一学就会的ROS基础入门教程 】03-1 ROS基础编程:ROS工作空间的创建、话题topic的发布与接收、以及话题消息的自定义使用

    [一学就会的ROS基础入门教程 ]03-1 ROS基础编程:ROS工作空间的创建.话题topic的发布与接收.以及话题消息的自定义使用 文前白话 1.创建工作空间与功能包 关于工作空间的介绍 创建开发 ...

  9. Netty简单实现客户端与服务端收发消息

    Netty简单实现客户端与服务端收发消息 这个小案例主要是实现netty收发消息,分为客户端,及服务端,以及包含了相关状态处理,主要的代码会放在最后 gitHub 地址上,有需要可以看一下 首先来简单 ...

最新文章

  1. php如何隐藏入口文件,PHP怎样隐藏入口文件
  2. C# 设置Menustrip提示框的显示
  3. 学习笔记Hadoop(一)—— Hadoop介绍(1)——认识大数据
  4. Topo系统的益处和帮助
  5. 航空企业如何用「AI利器」提升乘客体验
  6. 一键导出/备份「有道云笔记」工具
  7. HDU - 3746 Cyclic Nacklace(KMP的next数组判循环节)
  8. 项目测试基础:白盒测试相关知识笔记
  9. .NET开发框架(一)-框架介绍与视频演示
  10. java监听双按键_java 键盘监听 按一次键监听到两次
  11. java大致了解_学习Java第一天,大致了解
  12. 11.高性能MySQL --- 可扩展MySQL
  13. OpenGL ES总结(四)OpenGL 渲染视频画面
  14. vscode通过ssh远程连接服务器
  15. ImageNet 2012 中文标签(Chinese Labels)
  16. HorizontalScrollView+recyclerView
  17. 抖音吸粉_抖音吸粉六大技巧
  18. java无效的参数_java.sql.SQLException: 调用中无效的参数
  19. 服务器usb驱动安装系统安装失败怎么办,usb驱动安装不成功,小编教你usb驱动安装失败的解决方法...
  20. 微型计算机原理及接口技术张云龙答案,电子职业技能训练报告2.docx

热门文章

  1. Veeam FAQ系列转载(二)
  2. Spring Boot学习总结(19)——使用Redisson实现分布式锁
  3. Beetl学习总结(4)——Web集成
  4. 50道编程小题目之【无重复的三位数】
  5. php 时间戳存储 原因,将php文件中的unix时间戳存储到mysql中(store unix timestamp from php file into mysql)...
  6. requests模块报错:Use body.encode('utf-8') if you want to send it encoded in UTF-8.
  7. 为什么DevOps和SRE职位这么难招人?
  8. Windows安全不能靠本地管理员权限
  9. synchronized方法与synchronized代码块的区别
  10. mysql-5.6.24-win32.zip 下载 安装 配置 创建数据库