• [技术干货] WebSocket协议在java中的使用
    学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需写作干货注入能量… 热爱写作,愿意让自己成为更好的人…一、WebSocket介绍WebSocket 是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。1.Http和WebSocket比较:2.应用场景视频弹窗网页聊天体育实况更新股票基金报价实时更新二、WebSocket使用步骤1.客户端搭建博主这里使用案例的一个websocket.html页面作为WebSocket客户端,能够迅速的让我们了解通过WebSocket客户端与服务端之间的联系。 websocket.html页面效果如下:网页代码如下:<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>WebSocket Demo</title> </head> <body> <input id="text" type="text" /> <button onclick="send()">发送消息</button> <button onclick="closeWebSocket()">关闭连接</button> <div id="message"> </div> </body> <script type="text/javascript"> var websocket = null; var clientId = Math.random().toString(36).substr(2); //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ //连接WebSocket节点 websocket = new WebSocket("ws://localhost:8080/ws/"+clientId); } else{ alert('Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(){ setMessageInnerHTML("连接成功"); } //接收到消息的回调方法 websocket.onmessage = function(event){ setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //发送消息 function send(){ var message = document.getElementById('text').value; websocket.send(message); } //关闭连接 function closeWebSocket() { websocket.close(); } </script> </html>2.导入maven坐标代码如下(示例):<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>3.导入WebSocket服务端组件WebSocketServer,用于和客户端通信WebSocketServer.java代码如下(示例):package com.sky.websocket; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * WebSocket服务 */ @Component @ServerEndpoint("/ws/{sid}") public class WebSocketServer { //存放会话对象 private static Map<String, Session> sessionMap = new HashMap(); /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { System.out.println("客户端:" + sid + "建立连接"); sessionMap.put(sid, session); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, @PathParam("sid") String sid) { System.out.println("收到来自客户端:" + sid + "的信息:" + message); } /** * 连接关闭调用的方法 * * @param sid */ @OnClose public void onClose(@PathParam("sid") String sid) { System.out.println("连接断开:" + sid); sessionMap.remove(sid); } /** * 群发 * * @param message */ public void sendToAllClient(String message) { Collection<Session> sessions = sessionMap.values(); for (Session session : sessions) { try { //服务器向客户端发送消息 session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } }1.@ServerEndpoint主要是将目前的类定义成一个websocket服务器端, 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 @ServerEndpoint("/ws/{sid}")注解是跟客户端中的连接WebSocket节点中的代码对应: 其中的Session是指当前服务端与客户端之间的会话2.@OnOpen@OnOpen注解表示当客户端连接上服务端时触发,加上@OnOpen后的方法就变成了回调方法。(建立连接的时候会调用)3.@OnMessage@OnMessage注解表示收到客户端发来的消息时触发。4.@OnClose@OnClose注解表示当连接关闭时触发。4.导入配置类WebSocketConfiguration,注册WebSocket的服务端组件WebSocketConfiguration.java代码如下(示例)package com.sky.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * WebSocket配置类,用于注册WebSocket的Bean */ @Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }5.导入定时任务类WebSocketTask,定时向客户端推送数据WebSocketTask.java代码如下(示例)package com.sky.task; import com.sky.websocket.WebSocketServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @Component public class WebSocketTask { @Autowired private WebSocketServer webSocketServer; /** * 通过WebSocket每隔5秒向客户端发送消息 */ @Scheduled(cron = "0/5 * * * * ?") public void sendMessageToClient() { webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now())); } }三、演示结果当我们运行项目后,点击WebSocket.html,在服务端的控制台会出现连接成功字样,此时调用的是OnOpen回方法:客户端每隔五秒收到来自服务端的消息:客户端也能向服务端进行通信:当我们点击关闭连接的时候也会在服务端的控制台输出:刷新页面也会建立新的连接:总结以上就是WebSocket协议在java中的应用的相关知识点,希望对你有所帮助。 积跬步以至千里,积怠惰以至深渊。时代在这跟着你一起努力哦!
  • [技术干货] 实现web实时消息推送的方案--SSE
    很多人可能不知道,服务端向客户端推送消息,其实除了可以用WebSocket这种耳熟能详的机制外,还有一种服务器发送事件(Server-sent events),简称SSE。SSE它是基于HTTP协议的,我们知道一般意义上的HTTP协议是无法做到服务端主动向客户端推送消息的,但SSE是个例外,它变换了一种思路。SSE在服务器和客户端之间打开一个单向通道,服务端响应的不再是一次性的数据包而是text/event-stream类型的数据流信息,在有数据变更时从服务器流式传输到客户端。整体的实现思路有点类似于在线视频播放,视频流会连续不断的推送到浏览器,你也可以理解成,客户端在完成一次用时很长(网络不畅)的下载。SSE与WebSocket作用相似,都可以建立服务端与浏览器之间的通信,实现服务端向客户端推送消息,但还是有些许不同:SSE 是基于HTTP协议的,它们不需要特殊的协议或服务器实现即可工作; WebSocket需单独服务器来处理协议。SSE 单向通信,只能由服务端向客户端单向通信;webSocket全双工通信,即通信的双方可以同时发送和接受信息。SSE 实现简单开发成本低,无需引入其他组件;WebSocket传输数据需做二次解析,开发门槛高一些。SSE 默认支持断线重连;WebSocket则需要自己实现。SSE 只能传送文本消息,二进制数据需要经过编码后传送;WebSocket默认支持传送二进制数据。SSE 与 WebSocket 该如何选择?“ 技术并没有好坏之分,只有哪个更合适SSE好像一直不被大家所熟知,一部分原因是出现了WebSockets,这个提供了更丰富的协议来执行双向、全双工通信。对于游戏、即时通信以及需要双向近乎实时更新的场景,拥有双向通道更具吸引力。但是,在某些情况下,不需要从客户端发送数据。而你只需要一些服务器操作的更新。比如:站内信、未读消息数、状态更新、股票行情、监控数量等场景,SEE不管是从实现的难易和成本上都更加有优势。此外,SSE 具有WebSockets在设计上缺乏的多种功能,例如:自动重新连接、事件ID和发送任意事件的能力。前端只需进行一次HTTP请求,带上唯一ID,打开事件流,监听服务端推送的事件就可以了<script> let source = null; let userId = 7777 if (window.EventSource) { // 建立连接 source = new EventSource('http://localhost:7777/sse/sub/'+userId); setMessageInnerHTML("连接用户=" + userId); /** * 连接一旦建立,就会触发open事件 * 另一种写法:source.onopen = function (event) {} */ source.addEventListener('open', function (e) { setMessageInnerHTML("建立连接。。。"); }, false); /** * 客户端收到服务器发来的数据 * 另一种写法:source.onmessage = function (event) {} */ source.addEventListener('message', function (e) { setMessageInnerHTML(e.data); }); } else { setMessageInnerHTML("你的浏览器不支持SSE"); }</script>服务端的实现更简单,创建一个SseEmitter对象放入sseEmitterMap进行管理tic Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();/** * 创建连接 * * @date: 2022/7/12 14:51 * @auther: 公众号:程序员小富 */public static SseEmitter connect(String userId) { try { // 设置超时时间,0表示不过期。默认30秒 SseEmitter sseEmitter = new SseEmitter(0L); // 注册回调 sseEmitter.onCompletion(completionCallBack(userId)); sseEmitter.onError(errorCallBack(userId)); sseEmitter.onTimeout(timeoutCallBack(userId)); sseEmitterMap.put(userId, sseEmitter); count.getAndIncrement(); return sseEmitter; } catch (Exception e) { log.info("创建新的sse连接异常,当前用户:{}", userId); } return null;}/** * 给指定用户发送消息 * * @date: 2022/7/12 14:51 * @auther: 公众号:程序员小富 */public static void sendMessage(String userId, String message) { if (sseEmitterMap.containsKey(userId)) { try { sseEmitterMap.get(userId).send(message); } catch (IOException e) { log.error("用户[{}]推送异常:{}", userId, e.getMessage()); removeUser(userId); } }}我们模拟服务端推送消息,看下客户端收到了消息,和我们预期的效果一致。注意: SSE不支持IE浏览器,对其他主流浏览器兼容性做的还不错。转载自https://www.studyjava.cn/post/2004
  • [技术干货] 实现web实时消息推送的方案--iframe流
    iframe流就是在页面中插入一个隐藏的<iframe>标签,通过在src中请求消息数量API接口,由此在服务端和客户端之间创建一条长连接,服务端持续向iframe传输数据。这种方式实现简单,前端只要一个<iframe>标签搞定了<iframe src="/iframe/message" style="display:none"></iframe>服务端直接组装html、js脚本数据向response写入就行了@Controller@RequestMapping("/iframe")public class IframeController { @GetMapping(path = "message") public void message(HttpServletResponse response) throws IOException, InterruptedException { while (true) { response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setHeader("Cache-Control", "no-cache,no-store"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().print(" <script type=\"text/javascript\">\n" + "parent.document.getElementById('clock').innerHTML = \"" + count.get() + "\";" + "parent.document.getElementById('count').innerHTML = \"" + count.get() + "\";" + "</script>"); } }}但我个人不推荐,因为它在浏览器上会显示请求未加载完,图标会不停旋转,简直是强迫症杀手转载自https://www.studyjava.cn/post/2004
  • [技术干货] 实现web实时消息推送的方案--长轮询
    长轮询是对上边短轮询的一种改进版本,在尽可能减少对服务器资源浪费的同时,保证消息的相对实时性。长轮询在中间件中应用的很广泛,比如Nacos和apollo配置中心,消息队列kafka、RocketMQ中都有用到长轮询。这次我使用apollo配置中心实现长轮询的方式,应用了一个类DeferredResult,它是在servelet3.0后经过Spring封装提供的一种异步请求机制,直意就是延迟结果。DeferredResult可以允许容器线程快速释放占用的资源,不阻塞请求线程,以此接受更多的请求提升系统的吞吐量,然后启动异步工作线程处理真正的业务逻辑,处理完成调用DeferredResult.setResult(200)提交响应结果。下边我们用长轮询来实现消息推送。因为一个ID可能会被多个长轮询请求监听,所以我采用了guava包提供的Multimap结构存放长轮询,一个key可以对应多个value。一旦监听到key发生变化,对应的所有长轮询都会响应。前端得到非请求超时的状态码,知晓数据变更,主动查询未读消息数接口,更新页面数据。@Controller@RequestMapping("/polling")public class PollingController { // 存放监听某个Id的长轮询集合 // 线程同步结构 public static Multimap<String, DeferredResult<String>> watchRequests = Multimaps.synchronizedMultimap(HashMultimap.create()); /** * 公众号:程序员小富 * 设置监听 */ @GetMapping(path = "watch/{id}") @ResponseBody public DeferredResult<String> watch(@PathVariable String id) { // 延迟对象设置超时时间 DeferredResult<String> deferredResult = new DeferredResult<>(TIME_OUT); // 异步请求完成时移除 key,防止内存溢出 deferredResult.onCompletion(() -> { watchRequests.remove(id, deferredResult); }); // 注册长轮询请求 watchRequests.put(id, deferredResult); return deferredResult; } /** * 公众号:程序员小富 * 变更数据 */ @GetMapping(path = "publish/{id}") @ResponseBody public String publish(@PathVariable String id) { // 数据变更 取出监听ID的所有长轮询请求,并一一响应处理 if (watchRequests.containsKey(id)) { Collection<DeferredResult<String>> deferredResults = watchRequests.get(id); for (DeferredResult<String> deferredResult : deferredResults) { deferredResult.setResult("我更新了" + new Date()); } } return "success"; }当请求超过设置的超时时间,会抛出AsyncRequestTimeoutException异常,这里直接用@ControllerAdvice全局捕获统一返回即可,前端获取约定好的状态码后再次发起长轮询请求,如此往复调用。@ControllerAdvicepublic class AsyncRequestTimeoutHandler { @ResponseStatus(HttpStatus.NOT_MODIFIED) @ResponseBody @ExceptionHandler(AsyncRequestTimeoutException.class) public String asyncRequestTimeoutHandler(AsyncRequestTimeoutException e) { System.out.println("异步请求超时"); return "304"; }}我们来测试一下,首先页面发起长轮询请求/polling/watch/10086监听消息更变,请求被挂起,不变更数据直至超时,再次发起了长轮询请求;紧接着手动变更数据/polling/publish/10086,长轮询得到响应,前端处理业务逻辑完成后再次发起请求,如此循环往复。长轮询相比于短轮询在性能上提升了很多,但依然会产生较多的请求,这是它的一点不完美的地方。转载自studyjava.cn/post/2004
  • [技术干货] 实现web实时消息推送的方案--短轮询
    轮询(polling)应该是实现消息推送方案中最简单的一种,这里我们暂且将轮询分为短轮询和长轮询。短轮询很好理解,指定的时间间隔,由浏览器向服务器发出HTTP请求,服务器实时返回未读消息数据给客户端,浏览器再做渲染显示。一个简单的JS定时器就可以搞定,每秒钟请求一次未读消息数接口,返回的数据展示即可。效果还是可以的,短轮询实现固然简单,缺点也是显而易见,由于推送数据并不会频繁变更,无论后端此时是否有新的消息产生,客户端都会进行请求,势必会对服务端造成很大压力,浪费带宽和服务器资源。转载自https://www.studyjava.cn/post/2004
  • [技术干货] python 实现websocket服务器
    背景总所周知,现在是一个大前端的时代。很多原生开发,例如Android、IOS、MFC桌面端基本都被JS技术(Vue、React)给取代了。而在JS双向通信中,用的最多的就是websocket技术了。因此,本文讲解如何使用Python来实现一个websocket服务器代码实战要在 Python 中实现一个简单的 WebSocket 服务器,可以使用 websockets 库。首先,确保安装了 websockets 库:pip install websockets 接下来,编写一个简单的 WebSocket 服务器:import asyncio import websockets async def echo_server(websocket, path): async for message in websocket: print(f"Received message: {message}") await websocket.send(f"Echo: {message}") start_server = websockets.serve(echo_server, "localhost", 8765) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() 这段代码创建了一个简单的 WebSocket 服务器,监听在 localhost:8765 处。当客户端连接并发送消息时,服务器会原样返回消息。要测试这个 WebSocket 服务器,你可以使用浏览器或者其他的 WebSocket 客户端。以下是一个使用 JavaScript 编写的简单客户端示例:<!DOCTYPE html> <html> <head> <title>WebSocket Test</title> <script> const socket = new WebSocket("ws://localhost:8765"); socket.addEventListener("open", (event) => { console.log("Connected to WebSocket server"); socket.send("Hello, WebSocket server!"); }); socket.addEventListener("message", (event) => { console.log("Received from server:", event.data); }); socket.addEventListener("close", (event) => { console.log("Disconnected from WebSocket server"); }); </script> </head> <body> <h1>WebSocket Test</h1> </body> </html> 将这个 HTML 文件保存为 index.html,然后使用 Python 运行 WebSocket 服务器。在浏览器中打开 index.html,你将看到服务器和客户端之间的消息交互。注意:这个示例仅用于演示目的,实际应用中可能需要考虑更多因素,如错误处理、心跳检测、升级为 HTTP/1.1 协议等。总结python中提供了很多库,方便我们通过少量的代码调用,来实现具体的应用。因此,当遇到问题的时候,可以先在网上搜索下是否有相关的库可以解决该问题,不急着自己实现
  • [技术干货] WebSocket-转载
    一,什么是websocket WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议) 它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的 Websocket是一个持久化的协议 二,websocket的原理 websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信 在websocket出现之前,web交互一般是基于http协议的短连接或者长连接 websocket是一种全新的协议,不属于http无状态协议,协议名为"ws" 三,websocket与http的关系   相同点:  都是基于tcp的,都是可靠性传输协议 都是应用层协议 不同点:  WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息 HTTP是单向的 WebSocket是需要浏览器和服务器握手进行建立连接的 而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接  联系:  WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的 总结(总体过程):  首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等; 然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据; 最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。 四,websocket解决的问题 1.http存在的问题 http是一种无状态协议,每当一次会话完成后,服务端都不知道下一次的客户端是谁,需要每次知道对方是谁,才进行相应的响应,因此本身对于实时通讯就是一种极大的障碍 http协议采用一次请求,一次响应,每次请求和响应就携带有大量的header头,对于实时通讯来说,解析请求头也是需要一定的时间,因此,效率也更低下 最重要的是,需要客户端主动发,服务端被动发,也就是一次请求,一次响应,不能实现主动发送 2.long poll(长轮询) 对于以上情况就出现了http解决的第一个方法——长轮询 基于http的特性,简单点说,就是客户端发起长轮询,如果服务端的数据没有发生变更,会 hold 住请求,直到服务端的数据发生变化,或者等待一定时间超时才会返回。返回后,客户端又会立即再次发起下一次长轮询 优点是解决了http不能实时更新的弊端,因为这个时间很短,发起请求即处理请求返回响应,实现了“伪·长连接” 张三取快递的例子,张三今天一定要取到快递,他就一直站在快递点,等待快递一到,立马取走  从例子上来看有个问题:  假如有好多人一起在快递站等快递,那么这个地方是否足够大,(抽象解释:需要有很高的并发,同时有很多请求等待在这里) 总的来看: 推送延迟。服务端数据发生变更后,长轮询结束,立刻返回响应给客户端。  服务端压力。长轮询的间隔期一般很长,例如 30s、60s,并且服务端 hold 住连接不会消耗太多服务端资源。  3.Ajax轮询 基于http的特性,简单点说,就是规定每隔一段时间就由客户端发起一次请求,查询有没有新消息,如果有,就返回,如果没有等待相同的时间间隔再次询问 优点是解决了http不能实时更新的弊端,因为这个时间很短,发起请求即处理请求返回响应,把这个过程放大n倍,本质上还是request = response 举个形象的例子(假设张三今天有个快递快到了,但是张三忍耐不住,就每隔十分钟给快递员或者快递站打电话,询问快递到了没,每次快递员就说还没到,等到下午张三的快递到了,but,快递员不知道哪个电话是张三的,(可不是只有张三打电话,还有李四,王五),所以只能等张三打电话,才能通知他,你的快递到了)  从例子上来看有两个问题:  假如说,张三打电话的时间间隔为10分钟,当他收到快递前最后一次打电话,快递员说没到,他刚挂掉电话,快递入库了(就是到了),那么等下一次时间到了,张三打电话知道快递到了,那么这样的通讯算不算实时通讯?很显然,不算,中间有十分钟的时间差,还不算给快递员打电话的等待时间(抽象的解释:每次request的请求时间间隔等同于十分钟,请求解析相当于等待) 假如说张三所在的小区每天要收很多快递,每个人都采取主动给快递员打电话的方式,那么快递员需要以多快的速度接到,其他人打电话占线也是问题(抽象解释:请求过多,服务端响应也会变慢) 总的来看,Ajax轮询存在的问题: 推送延迟。  服务端压力。配置一般不会发生变化,频繁的轮询会给服务端造成很大的压力。  推送延迟和服务端压力无法中和。降低轮询的间隔,延迟降低,压力增加;增加轮询的间隔,压力降低,延迟增高  4.websocket的改进 一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端中断连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实现了“真·长链接”,实时性优势明显。      WebSocket有以下特点:  是真正的全双工方式,建立连接后客户端与服务器端是完全平等的,可以互相主动请求。而HTTP长连接基于HTTP,是传统的客户端对服务器发起请求的模式。 HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,信息交换效率很低。Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据,这显然和原有的HTTP协议有区别所以它需要对服务器和客户端都进行升级才能实现(主流浏览器都已支持HTML5) ———————————————— 版权声明:本文为CSDN博主「ohana!」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_54773998/article/details/123863493 
  • [问题求助] AICC 8.15.0 CC-Gateway 强制签入问题
    【问题来源】【必填】**【问题简要】【必填】话务员已经签入,再次签入的时候提示强制签入,调用 onlineagent/forcelogin 接口,进行强制签入,强制签入过程中websocket突然断开连接。【问题类别】CC-Gateway【AICC解决方案版本】AICC 8.15.0 CC-Gateway【期望解决时间】【选填】尽快【问题现象描述】【必填】目的:座席需要签入软件电话,结果没能签入成功。过程:话务员已经签入,再次签入的时候提示强制签入,调用 onlineagent/forcelogin 接口,进行强制签入,强制签入过程中websocket突然断开连接。请描述环境信息:广西。【日志或错误截图】【可选】//如果有日志或错误截图,请作为附件上传,如果问题日志中涉及到保密信息部分,请发邮件到libin@huawei.com 或 heping13@huawei.com 邮箱【附件】【可选】// 无
  • [问题求助] AICC 8.15.0 CC-Gateway 强制签入之后,突然断开webSocket连接
    问题描述: 软件电话签入,发现已经签入了。所以调用强制签入接口:'onlineagent/forcelogin',在强制签入过程中,收到各种事件,突然就中断webSocket连接了;流程如上图
  • [问题求助] 【SMC3.0】【websocket建链】1.3.6.1 Websocket 建链报401
    【功能模块】根据文档《SMC 21.0.1.SPC1 API参考(会议&维护)》第【1.3.6.1 Websocket 建链】章节,在与SMC3.0建立websocket链接时,报401【操作步骤&问题现象】根据文档《SMC 21.0.1.SPC1 API参考(会议&维护)》第【1.3.6.1 Websocket 建链】章节,在与SMC3.0建立websocket链接时,报401,大致过程如下:1、客户端使用String.valueOf(System.currentTimeMillis())生成timestamp;2、根据文档第【1.3.12.5 获取会议服务器ticket】章节,调用接口获取ticket;3、根据文档第【2.3.1.1 获取Token】章节,获取会议管理token,请求地址:/conf-portal/tokens,取值为返回值的uuid;4、根据文档第【1.3.6.1 Websocket 建链】,调用接口建立socket链接,请求链接为:wss://222.240.96.49:2443/conf-portal/websocket?timestamp=1649729013039&signature=32b0c95382b8c588e8ce854ddef8c24f45f8bb3749cfa20b7998b77831400785&username=smc15、以上链接设置请求头,再次调用,接口报相同错误headers:{"Authorization":"Basic c21jMTpobn******"}【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【AppCube】【实时告警推送功能】websocket连接500错误
    【功能模块】告警弹框1、天津渤海石化现场环境,版本20.3spc1【操作步骤&问题现象】1、无法实时推送2、wss错误500【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] HTML5 WebSocket技术使用详解
    WebSocketWebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客服端的浏览器,这种方式有一个很大的弊端,就是会占用很多的带宽。最新的轮询效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。使用WebSocket,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送。而且它为我们实现即时服务带来了两大好处:节省资源:互相沟通的Header是很小的-大概只有 2 Bytes。推送信息:不需要客户端请求,服务器可以主动传送数据给客户端。socket.ioSocket.IO是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。socket.io的特点易用性:socket.io封装了服务端和客户端,使用起来非常简单方便。跨平台:socket.io支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。自适应:它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5。WebSocket 安装部署1npm install socket.io服务监听socket.io的服务端启动非常的简单,引用socket.io模块。1var io = require('socket.io');然后调用listen函数,传入监听的端口号,开始服务监听。启用了80端口用于测试:1var io = require('socket.io')(80);注册事件12345io.on('connection', function (socket) {  socket.on('disconnect', function () {   })})connection事件在客户端成功连接到服务端时触发,有了这个事件,我们可以随时掌握用户连接到服务端的信息。当客户端成功建立连接时,在connection事件的回调函数中,我们还是可以为socket注册一些常用的事件,如:disconnect事件,它在客户端连接断开是触发,这时候我就知道用户已经离开了。WebSocket 启动服务目前为止,我们已经搭建好了一个最简单的socket服务器,为了在浏览器中能够访问到我们的服务,我们还需要在服务端搭建一个简单的web服务器,让浏览器能够访问我们的客户端页面。为了便捷,我们选用node.js中常用的express框架来实现web服务,示例如下:1234567891011var express = require('express');var app = express();app.get('/', function (req, res) {  res.status(200).send('成功连接!')});var server = require('http').createServer(app);var io = require('socket.io')(server);io.on('connection', function (socket) { });server.listen(80);WebSocket 客户端引用服务端构建完毕,下面看一看客户端应该如何使用。服务端运行后会在根目录动态生成socket.io的客户端js文件,客户端可以通过固定路径/socket.io/socket.io.js添加引用。首先添加网页index.html,并在网页中引用客户端js文件:1<script src="//cdn.bootcss.com/socket.io/2.0.2/socket.io.js"></script>WebSocket 连接服务当客户端成功加载socket.io客户端文件后会获取到一个全局对象io,我们将通过io.connect函数来向服务端发起连接请求。1234567var socket = io.connect('/');socket.on('connect',function(){  //连接成功});socket.on('disconnect',function(data){  //连接断开});connect函数可以接受一个url参数,url可以socket服务的http完整地址,也可以是相对路径,如果省略则表示默认连接当前路径。与服务端类似,客户端也需要注册相应的事件来捕获信息,不同的是客户端连接成功的事件是connect。了解了客户端如何使用,下面我们创建网页index.html,并添加如下内容(保存):123456789101112131415<html><head>  <script src="//cdn.bootcss.com/socket.io/2.0.2/socket.io.js"></script>  <script>    window.onload = function(){      var socket = io.connect('/');      socket.on('connect',function(){        document.write('连接成功!');      });    };  </script></head><body></body></html>页面添加完毕还要记得在服务端app.js中为它添加路由,让我们可以访问测试网页:123app.get('/index',function(req,res){  res.sendFile('index.html',{root:__dirname});});WebSocket 实时通讯服务端和客户端都构建完毕了,下面开始发送消息。当我们成功建立连接后,我们可以通过socket对象的send函数来互相发送消息,示例-客户端向服务端发送消息(index.html):12345678var socket = io.connect('/');socket.on('connect',function(){  //客户端连接成功后发送消息'hello world!'  socket.send('hello world!');});socket.on('message',function(data){  alert(data);});连接成功后,我们向服务端发送消息hello world!,还为socket注册了message事件,它是send函数对应的接收消息的事件,当服务端向客户端send消息时,我们就可以在message事件中接收到发送过来的消息。服务端向客户端发送消息也可以通过send的方式,示例 - 服务端向客户端发送消息(app.js):1234567var io = require('scoket.io');io.on('connection', function (socket) {  socket.send('Hello World!');  socket.on('message', function (data) {    console.log(data);  })});与客户端相同,服务端也需要为socket注册message事件来接收客户端发送过来的消息。WebSocket 发送信息socket.io既然是用来实现通讯的,那么如何发送、接收信息才是根本。在socket.io中,emit函数用于发送数据,我们使用send的方式实现了信息的互发,其实send函数只是emit的封装,实际上还是使用了emit,且看send函数是如何实现的:123456function send(){ var args = toArray(arguments); args.unshift('message'); this.emit.apply(this, args); return this;}在send函数中,获取到原来的参数,并在原来的基础上插入了一个参数message,然后调用了emit函数。通过send函数的实现,我们也学会了emit函数的用法,它有多个参数,第一个参数是事件名称,在接收端注册该事件就可以接收到发送过去的信息,事件名称可以自由定义,在不同的场景下,我们可以定义不同的事件来接收消息。第二个参数才是发送的数据。了解清楚了工作原理,下面来将send替换成emit函数发送信息:123456//app.jsio.on('connection',function(socket){   socket.emit('message','连接成功!');   socket.on('message',function(data){  });});WebSocket 服务端事件事件监听是实现通讯的基础,因此充分了解socket.io的事件,学习如何在正确的时候使用它们至关重要。在一些关键的的状态下,socket.io可以注册相应的事件,通过事件监听,我们可以在这些事件中作出反应,常用的事件如下:connection——客户端成功连接到服务器。message——捕获客户端send信息。。disconnect——客户端断开连接。error——发生错误。WebSocket 客户端较服务端而言,客户端提供更多的监听事件,在实时应用中,我们可以为这些事件注册监听并作出反应,例如:connect提示用户连接成功,disconnect时提示用户停止服务等等。connection——成功连接到服务器。connecting——正在连接。disconnect——断开连接。connect_failed——连接失败。error——连接错误。message——监听服务端send的信息。reconnect_failed——重新连接失败。reconnect——重新连接成功。reconnecting——正在重连。那么客户端socket发起连接时的顺序是怎么样的呢?当第一次连接时,事件触发顺序为: connecting → connect;当失去连接时,事件触发顺序为:disconnect → reconnecting → connecting → reconnect → connect。WebSocket 命名空间命名空间着实是一个非常实用好用的功能。我们可以通过命名空间,划分出不同的房间,在房间里的广播和通信都不会影响到房间以外的客户端。那么如何创建房间呢?在服务端,通过of("")的方式来划分新的命名空间:12io.of('chat').on('connection',function(socket){});示例中,我们创建一个名为chat的房间,客户端可以通过如下方式连接到指定的房间:1var socket = io.connect('/chat');虽然连接到指定的房间,但是我们也可以在服务端操作,自由的进出房间:12socket.join('chat');//进入chat房间socket.leave('chat');//离开chat房间WebSocket 广播消息在实时应用中,广播是一个不可或缺的功能,socket.io提供两种服务端广播方式。第一种广播方式可以称之为'全局广播',顾名思义,全局广播就是所有连接到服务器的客户端都会受到广播的信息:1socket.broadcast.emit('DATA',data);但是,在实际应用场景中,我们很多时候并不需要所有用户都收到广播信息,有的广播信息只发送给一部分客户端,比如某个房间里面的用户,那么可以使用如下方式:1socket.broadcast.to('chat').emit('DATA',data);中间件socket.io提供中间件功能,我们可以通过中间件来对请求进行预处理,比如身份验证:1234io.use(function(socket, next){ if (socket.request.headers.cookie) return next(); next(new Error('Authentication error'));});示例中展示了通过中间件进行身份验证,当没有cookie的时候抛出异常。传递参数在很多应用场景中,客户端发起连接请求时都需要传递参数,这些参数可能是身份验证、初始化设置等等,那么socket.io发起连接时如何传递参数呢?1var socket = io.connect('/');由于connect函数发起连接的参数是一个url,你可能会想到把参数拼接到url上,如http://xxxx?xx=xxxx,但是很遗憾这样是行不通的,我们可以通过这样的方式来传递参数:1var socket = io.connect('/',{ _query:'sid=123456' });在服务端可以这样获取到传递的参数:1234io.use(function(socket){   var query = socket.request._query;   var sid = query.sid; });客户端传递的参数已经被解析成了一个json对象,这个对象就是_query。
  • [问题求助] 在ROMA conect中,怎么建立Websocket长连接发送消息实现订阅?
     在ROMA conect开发中,怎么建立Websocket长连接发送消息实现订阅?
  • [问题求助] ROMA怎么实现Websocket订阅?
    【功能模块】在ROMA conect中,怎么使用Websocket发送消息实现订阅?可否提供参考文档?【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [新手课堂] Websocket协议
    概念:        Websocket 是HTML5出的东西(协议),也就是说HTTP协议没有变化,但HTTP是不支持持久连接的(长连接,循环连接的不算),          Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说,可以把 WebSocket 看成是 HTTP 协议为了支持长连接所打的一个大补丁 Websocket只需要一次HTTP握手,就可以做到源源不断的信息传送了。(在程序设计中,这种设计叫做回调,即:你有信息了再来通知我,而不是我傻乎乎的每次跑来问你), WebSocket 还是一个双通道的连接,在同一个 TCP 连接上可以多次 发 , 收 信息,由客户主动询问,转换为服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的。。)内容拓展:  HTTP1.0:  每次请求都要创建TCP连接(就是一个Request 对应一个Response)  HTTP1.1:  进行了改进,它默认开启长连接 keep-alive(使用keep-alive参数来告知服务器端要建立一个长连接) ,也就是说,在一个TCP连接中,可以发送多个Http的Request,接收多个Response(一个TCP连接上可以传送多个HTTP请求和响应)//在请求头header里,由浏览器/服务器添加Connection:keep-alive 备注:但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response 也是 被动的,不能主动发起。建立持久连接的方式:1: ajax轮询: 让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。                      request--->response , request--->response ,  request--->response ........ loop3: long poll :采取的是阻塞模型(一直打电话,没收到就不挂电话)                     request--->。。。。。。。reponse(没有消息,就不返回reponse,等待到有消息的时候,再给你(Response))                     下个消息获取再次建立连接:request--->。。。。reponse(没有消息,就不返回reponse)         所谓的 polling 是指从客户端(一般就是浏览器)不断主动的向服务器发 HTTP 请求 查询是否有新数据上面 两种方式都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,被动性(服务端不能主动联系客户端,只能有客户端发起)。3: webscoket: 只需建立一次连接后,就可以源源不断 收 ,发 信息了,形成了通道。
总条数:28 到第
上滑加载中