websocket 使用基于STOMP进行推送
- 格式:pdf
- 大小:334.59 KB
- 文档页数:3
使用WebSocket和Redis构建实时消息推送的技巧与实践WebSocket技术和Redis数据库在实时消息推送方面具有重要的作用。
WebSocket是一种基于TCP的全双工通信协议,可在客户端和服务器之间建立持久连接,实现实时的双向通信。
而Redis则是一个高性能的非关系型数据库,可用于存储和处理实时消息。
在构建实时消息推送系统时,使用WebSocket和Redis的组合可以提供可靠且高效的解决方案。
下面将介绍一些有关使用WebSocket和Redis构建实时消息推送的技巧与实践。
首先,利用WebSocket建立客户端与服务器的连接是构建实时消息推送系统的关键步骤。
使用WebSocket可以避免传统的轮询机制,节省了带宽和服务器资源。
通过WebSocket的长连接,服务器可以主动向客户端推送消息,实现实时的通信。
接下来,使用Redis作为消息队列来存储待推送的消息是一种常见的做法。
当服务器有新的消息需要推送时,将消息存储到Redis的队列中。
然后,客户端通过订阅Redis的消息通道来接收推送的消息。
Redis的高性能和可靠性保证了消息的快速存取与传输。
除了使用Redis作为消息队列外,还可以结合Redis的发布/订阅功能来实现实时消息推送。
发布/订阅模式允许多个订阅者同时接收同一条消息,非常适用于实时推送场景。
服务器将消息通过Redis的发布功能发布到指定的频道,而所有订阅该频道的客户端都能收到推送的消息。
在实际应用中,可以将WebSocket和Redis结合使用,以实现更复杂的实时消息推送功能。
例如,可以通过WebSocket获取客户端的连接信息,并利用Redis存储和管理这些连接信息。
这样,服务器可以根据客户端的订阅信息,有针对性地推送消息。
另外,为了提高系统的可扩展性和容错性,可以使用Redis的集群模式。
Redis 集群可以将数据分布在多个节点上,提供了更高的性能和可靠性。
同时,使用集群模式还可以实现横向扩展,应对大并发的请求。
使用Websocket和Servlet实现服务器定点推送作者:钱宇虹来源:《软件工程》2016年第10期摘要:针对Java Web实时系统中的消息推送这一关键问题,本文基于Tomcat8和WebSocket标准,提出并且实现了一个服务端定点推送模型,能够向指定的Web注册用户进行消息推送。
该模型具有非广播的特点,即在没有浏览器请求的情况下通过Servlet主动将消息推送至某个已注册的Web用户。
该模型已经成功地应用于呼叫中心系统中将电话分机状态和弹屏信息推送给Web坐席,该模型也可以用于即时消息、游戏应用、实时证券报价、股票系统等Web实时系统,具有广泛的使用价值。
关键词:Tomcat8;WebSocket;定点推送中图分类号:TP311 文献标识码:A1 引言(Introduction)众所周知,HTTP协议是基于请求-响应模式的无状态的单向协议,即每次都要由客户端(如浏览器)主动向服务端发出“请求”,服务端做出处理后将结果作为“响应”返回给客户端。
“无状态”指的是每次的请求-响应都必须经历建立连接和释放连接的过程,前一次连接和后一次连接相互之间没有关系。
“单向”指的是客户端是主动方,服务端是被动方,服务端不能主动向客户端发送数据。
HTTP协议的这一特点对传统的Web应用,像电子商务网站、搜索引擎等等非常合适,但是不能满足日益增强的实时性需求的Web应用,这些应用要求在无需客户端发出请求的前提下,服务端能实时地将信息主动推送到客户端,如基于Web的聊天系统、即时消息、游戏应用、实时证券报价和股票系统等。
过去,针对实时性较强的应用,开发人员使用轮询和Comet技术这些折中方案。
轮询就是客户端按照预先设置的时间间隔向服务端发送请求,周期性地查询是否有数据更新。
早期的轮询是通过在HTML头部插入META元信息来实现网页的自动刷新,后来人们使用AJAX轮询。
AJAX轮询带来的最大好处就是在不刷新整个页面的前提下可以实现网页的局部更新,既提高了做事的效率又增强了用户体验,但是AJAX还是受限于请求-响应模式,由于无法预期什么时候推送消息,造成很多无效的请求。
php实现websocket实时消息推送php实现websocket实时消息推送,供⼤家参考,具体内容如下SocketService.php<?php/*** Created by xwx* Date: 2017/10/18* Time: 14:33*/class SocketService{private $address = '0.0.0.0';private $port = 8083;private $_sockets;public function __construct($address = '', $port=''){if(!empty($address)){$this->address = $address;}if(!empty($port)) {$this->port = $port;}}public function service(){//获取tcp协议号码。
$tcp = getprotobyname("tcp");$sock = socket_create(AF_INET, SOCK_STREAM, $tcp);socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);if($sock < 0){throw new Exception("failed to create socket: ".socket_strerror($sock)."\n");}socket_bind($sock, $this->address, $this->port);socket_listen($sock, $this->port);echo "listen on $this->address $this->port ... \n";$this->_sockets = $sock;}public function run(){$this->service();$clients[] = $this->_sockets;while (true){$changes = $clients;$write = NULL;$except = NULL;socket_select($changes, $write, $except, NULL);foreach ($changes as $key => $_sock){if($this->_sockets == $_sock){ //判断是不是新接⼊的socketif(($newClient = socket_accept($_sock)) === false){die('failed to accept socket: '.socket_strerror($_sock)."\n");}$line = trim(socket_read($newClient, 1024));$this->handshaking($newClient, $line);//获取client ipsocket_getpeername ($newClient, $ip);$clients[$ip] = $newClient;echo "Client ip:{$ip} \n";echo "Client msg:{$line} \n";} else {socket_recv($_sock, $buffer, 2048, 0);$msg = $this->message($buffer);//在这⾥业务代码echo "{$key} clinet msg:",$msg,"\n";fwrite(STDOUT, 'Please input a argument:');$response = trim(fgets(STDIN));$this->send($_sock, $response);echo "{$key} response to Client:".$response,"\n";}}}}/*** 握⼿处理* @param $newClient socket* @return int 接收到的信息*/public function handshaking($newClient, $line){$headers = array();$lines = preg_split("/\r\n/", $line);foreach($lines as $line){$line = chop($line);if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)){$headers[$matches[1]] = $matches[2];}}$secKey = $headers['Sec-WebSocket-Key'];$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" ."Upgrade: websocket\r\n" ."Connection: Upgrade\r\n" ."WebSocket-Origin: $this->address\r\n" ."WebSocket-Location: ws://$this->address:$this->port/websocket/websocket\r\n"."Sec-WebSocket-Accept:$secAccept\r\n\r\n";return socket_write($newClient, $upgrade, strlen($upgrade));}/*** 解析接收数据* @param $buffer* @return null|string*/public function message($buffer){$len = $masks = $data = $decoded = null;$len = ord($buffer[1]) & 127;if ($len === 126) {$masks = substr($buffer, 4, 4);$data = substr($buffer, 8);} else if ($len === 127) {$masks = substr($buffer, 10, 4);$data = substr($buffer, 14);} else {$masks = substr($buffer, 2, 4);$data = substr($buffer, 6);}for ($index = 0; $index < strlen($data); $index++) {$decoded .= $data[$index] ^ $masks[$index % 4];}return $decoded;}/*** 发送数据* @param $newClinet 新接⼊的socket* @param $msg 要发送的数据* @return int|string*/public function send($newClinet, $msg){$msg = $this->frame($msg);socket_write($newClinet, $msg, strlen($msg));}public function frame($s) {$a = str_split($s, 125);if (count($a) == 1) {return " 81" . chr(strlen($a[0])) . $a[0];}$ns = "";foreach ($a as $o) {$ns .= " 81" . chr(strlen($o)) . $o;}return $ns;}/*** 关闭socket*/public function close(){return socket_close($this->_sockets);}}$sock = new SocketService();$sock->run();web.html<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no"> <title>websocket</title></head><body><input id="text" value=""><input type="submit" value="send" onclick="start()"><input type="submit" value="close" onclick="close()"><div id="msg"></div><script>/**0:未连接1:连接成功,可通讯2:正在关闭3:连接已关闭或⽆法打开*///创建⼀个webSocket 实例var webSocket = new WebSocket("ws://192.168.31.152:8083");webSocket.onerror = function (event){onError(event);};// 打开websocketwebSocket.onopen = function (event){onOpen(event);};//监听消息webSocket.onmessage = function (event){onMessage(event);};webSocket.onclose = function (event){onClose(event);}//关闭监听websocketfunction onError(event){document.getElementById("msg").innerHTML = "<p>close</p>";console.log("error"+event.data);};function onOpen(event){console.log("open:"+sockState());document.getElementById("msg").innerHTML = "<p>Connect to Service</p>";};function onMessage(event){console.log("onMessage");document.getElementById("msg").innerHTML += "<p>response:"+event.data+"</p>"};function onClose(event){document.getElementById("msg").innerHTML = "<p>close</p>";console.log("close:"+sockState());webSocket.close();}function sockState(){var status = ['未连接','连接成功,可通讯','正在关闭','连接已关闭或⽆法打开'];return status[webSocket.readyState];}function start(event){console.log(webSocket);var msg = document.getElementById('text').value;document.getElementById('text').value = '';console.log("send:"+sockState());console.log("msg="+msg);webSocket.send("msg="+msg);document.getElementById("msg").innerHTML += "<p>request"+msg+"</p>"};function close(event){webSocket.close();}</script></body></html>以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
基于WebSocket的实时消息推送的设计与实现作者:李伙钦来源:《科技视界》2015年第03期【摘要】随着互联网的飞速发展,网页中实时通讯和消息推送的应用愈加广泛。
传统上采用定时轮询或Comet的方式实现实时通讯,但对服务器负担较重。
全新的HTML5标准中引入了WebSocket,WebSocket实现了服务器与浏览器间的双向连接,基于事件方式,效率高,服务器负担轻。
本文使用Node.js平台和Socket.IO组件设计并实现了WebSocket实时消息推送网页应用。
【关键词】WebSocket; Socket.IO; Node.js0 引言随着互联网的高速发展,网页中实时通讯和消息推送的应用愈加广泛,如论坛中消息实时推送、商务网站中的QQ在线客服、淘宝中网页版阿里旺旺、股票实时报价、实时数据监控等,这些应用都需要浏览器与服务器间的双向通讯。
但是HTTP设计初衷是一种“请求-响应”的设计,即用户通过浏览器向服务器发出网页请求,浏览器将网页数据发给用户后就断开了与用户连接,请求都是由用户发起的,服务器只是被动的接收请求和反馈数据。
这种模式下,用户可以主动发数据给服务器,而服务器只能被动反馈数据,不能主动发数据给用户。
要实现实时通讯就需要“破解”这种单向的连接方式。
传统上常用解决办法是采用定时轮询方式和Comet方式,定时轮询是浏览器定时刷新页面,由浏览器主动发出请求,获取服务器上发给该用户的数据,这种方式轮询的时间间隔不好控制,还会造成大量无用请求,浪费服务器资源;而Comet是一种“长连接”设计,通过AJAX 向服务器发出请求,服务器端会阻塞请求直到有数据传递或超时才返回,浏览器接收到数据或者超时后立即发出新请求,以此保持浏览器与服务器间的连接,这种方式Comet会长时间占用一个连接,当有大量长连接时会服务器负担加重。
WebSocket的到来,解决了定时轮询方式和Comet方式无法根本解决的服务器负担难题。
Springboot+Netty+Websocket实现消息推送实例⽬录前⾔⼀、引⼊netty依赖⼆、使⽤步骤前⾔WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
在 WebSocket API 中,浏览器和服务器只需要完成⼀次握⼿,两者之间就直接可以创建持久性的连接,并进⾏双向数据传输。
Netty框架的优势1. API使⽤简单,开发门槛低;2. 功能强⼤,预置了多种编解码功能,⽀持多种主流协议;3. 定制能⼒强,可以通过ChannelHandler对通信框架进⾏灵活地扩展;4. 性能⾼,通过与其他业界主流的NIO框架对⽐,Netty的综合性能最优;5. 成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发⼈员不需要再为NIO的BUG⽽烦恼提⽰:以下是本篇⽂章正⽂内容,下⾯案例可供参考⼀、引⼊netty依赖<dependency><groupId>ty</groupId><artifactId>netty-all</artifactId><version>4.1.48.Final</version></dependency>⼆、使⽤步骤1.引⼊基础配置类package ty;public enum Cmd {START("000", "连接成功"),WMESSAGE("001", "消息提醒"),;private String cmd;private String desc;Cmd(String cmd, String desc) {this.cmd = cmd;this.desc = desc;}public String getCmd() {return cmd;}public String getDesc() {return desc;}}ty服务启动监听器package ty;import ty.bootstrap.ServerBootstrap;import ty.channel.ChannelFuture;import ty.channel.ChannelOption;import ty.channel.EventLoopGroup;import ty.channel.nio.NioEventLoopGroup;import ty.channel.socket.nio.NioServerSocketChannel;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.ApplicationRunner;import org.springframework.context.annotation.Bean;import ponent;/*** @author test* <p>* 服务启动监听器**/@Slf4j@Componentpublic class NettyServer {@Value("${ty.port}")private int port;@Autowiredprivate ServerChannelInitializer serverChannelInitializer;@BeanApplicationRunner nettyRunner() {return args -> {//new ⼀个主线程组EventLoopGroup bossGroup = new NioEventLoopGroup(1);//new ⼀个⼯作线程组EventLoopGroup workGroup = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap().group(bossGroup, workGroup).channel(NioServerSocketChannel.class).childHandler(serverChannelInitializer)//设置队列⼤⼩.option(ChannelOption.SO_BACKLOG, 1024)// 两⼩时内没有数据的通信时,TCP会⾃动发送⼀个活动探测数据报⽂.childOption(ChannelOption.SO_KEEPALIVE, true);//绑定端⼝,开始接收进来的连接try {ChannelFuture future = bootstrap.bind(port).sync();("服务器启动开始监听端⼝: {}", port);future.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {//关闭主线程组bossGroup.shutdownGracefully();//关闭⼯作线程组workGroup.shutdownGracefully();}};}}ty服务端处理器package ty;import mon.util.JsonUtil;import ty.channel.Channel;import ty.channel.ChannelHandler;import ty.channel.ChannelHandlerContext;import ty.channel.SimpleChannelInboundHandler;import ty.handler.codec.http.websocketx.TextWebSocketFrame;import ty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;import lombok.Data;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import ponent;import .URLDecoder;import java.util.*;/*** @author test* <p>* netty服务端处理器**/@Slf4j@Component@ChannelHandler.Sharablepublic class NettyServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Autowiredprivate ServerChannelCache cache;private static final String dataKey = "test=";@Datapublic static class ChannelCache {}/*** 客户端连接会触发*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();("通道连接已打开,ID->{}......", channel.id().asLongText());}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {Channel channel = ctx.channel();WebSocketServerProtocolHandler.HandshakeComplete handshakeComplete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;String requestUri = handshakeComplete.requestUri();requestUri = URLDecoder.decode(requestUri, "UTF-8");("HANDSHAKE_COMPLETE,ID->{},URI->{}", channel.id().asLongText(), requestUri);String socketKey = requestUri.substring(stIndexOf(dataKey) + dataKey.length());if (socketKey.length() > 0) {cache.add(socketKey, channel);this.send(channel, Cmd.DOWN_START, null);} else {channel.disconnect();ctx.close();}}erEventTriggered(ctx, evt);}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();("通道连接已断开,ID->{},⽤户ID->{}......", channel.id().asLongText(), cache.getCacheId(channel));cache.remove(channel);}/*** 发⽣异常触发*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {Channel channel = ctx.channel();log.error("连接出现异常,ID->{},⽤户ID->{},异常->{}......", channel.id().asLongText(), cache.getCacheId(channel), cause.getMessage(), cause); cache.remove(channel);ctx.close();}/*** 客户端发消息会触发*/@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {try {// ("接收到客户端发送的消息:{}", msg.text());ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.toString(Collections.singletonMap("cmd", "100"))));} catch (Exception e) {log.error("消息处理异常:{}", e.getMessage(), e);}}public void send(Cmd cmd, String id, Object obj) {HashMap<String, Channel> channels = cache.get(id);if (channels == null) {return;}Map<String, Object> data = new LinkedHashMap<>();data.put("cmd", cmd.getCmd());data.put("data", obj);String msg = JsonUtil.toString(data);("服务器下发消息: {}", msg);channels.values().forEach(channel -> {channel.writeAndFlush(new TextWebSocketFrame(msg));});}public void send(Channel channel, Cmd cmd, Object obj) {Map<String, Object> data = new LinkedHashMap<>();data.put("cmd", cmd.getCmd());data.put("data", obj);String msg = JsonUtil.toString(data);("服务器下发消息: {}", msg);channel.writeAndFlush(new TextWebSocketFrame(msg));}}ty服务端缓存类package ty;import ty.channel.Channel;import ty.util.AttributeKey;import ponent;import java.util.HashMap;import java.util.concurrent.ConcurrentHashMap;@Componentpublic class ServerChannelCache {private static final ConcurrentHashMap<String, HashMap<String, Channel>> CACHE_MAP = new ConcurrentHashMap<>(); private static final AttributeKey<String> CHANNEL_ATTR_KEY = AttributeKey.valueOf("test");public String getCacheId(Channel channel) {return channel.attr(CHANNEL_ATTR_KEY).get();}public void add(String cacheId, Channel channel) {channel.attr(CHANNEL_ATTR_KEY).set(cacheId);HashMap<String, Channel> hashMap = CACHE_MAP.get(cacheId);if (hashMap == null) {hashMap = new HashMap<>();}hashMap.put(channel.id().asShortText(), channel);CACHE_MAP.put(cacheId, hashMap);}public HashMap<String, Channel> get(String cacheId) {if (cacheId == null) {return null;}return CACHE_MAP.get(cacheId);}public void remove(Channel channel) {String cacheId = getCacheId(channel);if (cacheId == null) {return;}HashMap<String, Channel> hashMap = CACHE_MAP.get(cacheId);if (hashMap == null) {hashMap = new HashMap<>();}hashMap.remove(channel.id().asShortText());CACHE_MAP.put(cacheId, hashMap);}}ty服务初始化器package ty;import ty.channel.ChannelInitializer;import ty.channel.ChannelPipeline;import ty.channel.socket.SocketChannel;import ty.handler.codec.http.HttpObjectAggregator;import ty.handler.codec.http.HttpServerCodec;import ty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;import ty.handler.stream.ChunkedWriteHandler;import org.springframework.beans.factory.annotation.Autowired;import ponent;/*** @author test* <p>* netty服务初始化器**/@Componentpublic class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {@Autowiredprivate NettyServerHandler nettyServerHandler;@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();pipeline.addLast(new HttpServerCodec());pipeline.addLast(new ChunkedWriteHandler());pipeline.addLast(new HttpObjectAggregator(8192));pipeline.addLast(new WebSocketServerProtocolHandler("/test.io", true, 5000));pipeline.addLast(nettyServerHandler);}}6.html测试<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>test</title><script type="text/javascript">function WebSocketTest(){if ("WebSocket" in window){alert("您的浏览器⽀持 WebSocket!");// 打开⼀个 web socketvar ws = new WebSocket("ws://localhost:port/test.io");ws.onopen = function(){// Web Socket 已连接上,使⽤ send() ⽅法发送数据ws.send("发送数据");alert("数据发送中...");};ws.onmessage = function (evt){var received_msg = evt.data;alert("数据已接收...");};ws.onclose = function(){// 关闭 websocketalert("连接已关闭...");};}else{// 浏览器不⽀持 WebSocketalert("您的浏览器不⽀持 WebSocket!");}}</script></head><body><div id="sse"><a href="javascript:WebSocketTest()" rel="external nofollow" >运⾏ WebSocket</a></div></body></html>7.vue测试mounted() {this.initWebsocket();},methods: {initWebsocket() {let websocket = new WebSocket('ws://localhost:port/test.io?test=123456');websocket.onmessage = (event) => {let msg = JSON.parse(event.data);switch (msg.cmd) {case "000":this.$message({type: 'success',message: "建⽴实时连接成功!",duration: 1000})setInterval(()=>{websocket.send("heartbeat")},60*1000);break;case "001":this.$message.warning("收到⼀条新的信息,请及时查看!")break;}}websocket.onclose = () => {setTimeout(()=>{this.initWebsocket();},30*1000);}websocket.onerror = () => {setTimeout(()=>{this.initWebsocket();},30*1000);}},},;到此这篇关于Springboot+Netty+Websocket实现消息推送实例的⽂章就介绍到这了,更多相关Springboot Websocket消息推送内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
SpringBoot2.0整合WebSocket,实现后端数据实时推送!之前公司的某个系统为了实现推送技术,所⽤的技术都是Ajax轮询,这种⽅式浏览器需要不断的向服务器发出请求,显然这样会浪费很多的带宽等资源,所以研究了下WebSocket,本⽂将详细介绍下。
⼀、什么是WebSocket?WebSocket是HTML5开始提供的⼀种在单个TCP连接上进⾏全双⼯通讯的协议,能更好的节省服务器资源和带宽,并且能够更实时地进⾏通讯。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据,在WebSocket API中,浏览器和服务器只需要完成⼀次握⼿,两者之间就直接可以创建持久性的连接,并进⾏双向数据传输。
⼆、SpringBoot整合WebSocket新建⼀个spring boot项⽬spring-boot-websocket,按照下⾯步骤操作。
1. pom.xml引⼊jar包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>2. 新建WebSocket的配置类这个配置类检测带注解@ServerEndpoint的bean并注册它们,配置类代码如下:@Configurationpublic class WebSocketConfig {/*** 给spring容器注⼊这个ServerEndpointExporter对象* 相当于xml:* <beans>* <bean id="serverEndpointExporter" class="org.springframework.web.socket.server.standard.ServerEndpointExporter"/>* </beans>* <p>* 检测所有带有@serverEndpoint注解的bean并注册他们。
vue项⽬使⽤websocket实现数据实时推送写了⼀个关于⼯程的项⽬,关于⼯地数据的实时监控1.后端要先写好数据,将数据传递给前端2.在前端页⾯:$(function(){ var websocket = null;//判断当前浏览器是否⽀持WebSocketif ('WebSocket' in window) {websocket = new WebSocket("ws://localhost:9999/guanXiangCamera/websocket"); // 后台给的地址 // 这⾥会传递⼀些数据,}else {alert('当前浏览器 Not support websocket')}//连接发⽣错误的回调⽅法websocket.onerror = function () {setMessageInnerHTML("WebSocket连接发⽣错误");};//连接成功建⽴的回调⽅法websocket.onopen = function () {//setMessageInnerHTML("WebSocket连接成功");}//接收到消息的回调⽅法websocket.onmessage = function (event) {setMessageInnerHTML(event.data);}//连接关闭的回调⽅法websocket.onclose = function () {//setMessageInnerHTML("WebSocket连接关闭");}//监听窗⼝关闭事件,当窗⼝关闭时,主动去关闭websocket连接,防⽌连接还没断开就关闭窗⼝,server端会抛异常。
window.onbeforeunload = function () {//closeWebSocket();}//将消息显⽰在⽹页上function setMessageInnerHTML(innerHTML) {document.getElementById('message').innerHTML += innerHTML + '<br/>';}//关闭WebSocket连接function closeWebSocket() {websocket.close();}//发送消息function send() {var message = "测试⼀下,看能不能发!"websocket.send(message);}}注意:有写要求是⼀进去就要请求websocket返回数据的,或者是查看时再请求接⼝返回数据的。
基于Websocket的消息实时推送设计与实现
齐华;李佳;刘军
【期刊名称】《微处理机》
【年(卷),期】2016(037)003
【摘要】随着互联网技术的快速发展,基于B/S架构的实时通讯和消息推送的应用范围越来越广泛,服务器消息推送是很多应用中的一项重要功能,服务器推送技术的优劣直接影响着消息推送的效率.传统的解决方案有html refresh,定时轮询和comet,但这些实现方案存在着资源消耗大、执行效率低、服务器负担过大等缺陷.Html5中引入了websocket这一全双工通信协议,利用此技术实现的方案能够在减轻服务器负担的同时高效地对服务器消息进行实时推送.使用node.js平台和socket.io库技术设计并实现了一种基于websocket协议的服务器实时消息推送平台.运行测试结果显示能快速稳定地实现消息的实时服务器推送.
【总页数】5页(P36-39,43)
【作者】齐华;李佳;刘军
【作者单位】西安工业大学电子信息工程学院,西安710000;西安工业大学电子信息工程学院,西安710000;武警工程学院通信工程系,西安710086
【正文语种】中文
【中图分类】TP311.1
【相关文献】
1.基于WebSocket的车辆GPS信息实时推送系统的实现 [J], 钟波;陶智勇
2.基于WebSocket的消息推送系统 [J], 王佃来;宿爱霞;安晏辉
3.基于WebSocket模式的混合移动应用消息推送研究 [J], 马庆
4.基于WebSocket的实时消息推送的设计与实现 [J], 李伙钦
5.WebSocket在实时消息推送中的应用设计与实现 [J], 吴绍卫
因版权原因,仅展示原文概要,查看原文内容请购买。
Android中使⽤WebSocket实现群聊和消息推送功能(不使⽤WebView)WebSocket protocol 是HTML5⼀种新的协议。
它实现了浏览器与服务器全双⼯通信(full-duplex)。
WebSocket是Web2.0时代的新产物,⽤于弥补HTTP协议的某些不⾜,不过他们之间真实的关系是兄弟关系,都是对socket的进⼀步封装,其⽬前最直观的表现就是服务器推送和聊天功能。
更多知识参考:如何理解 TCP/IP, SPDY, WebSocket 三者之间的关系?今天的重点是讲如何在Android中脱离WebView使⽤WebSocket,⽽不是在Web浏览器使⽤,如果是在Web浏览器中使⽤,⽹上已经太多教程、框架和demo,没必要讲。
到⽬前为⽌我个⼈认为安卓端⽐较好⽤的WebSocketClient有:autobahn、AndroidAsync、Java-WebSocket。
好不好⽤其实需要看实际需求⽽定,此处我选择Java-WebSocket。
⼀、Android客户端的创建(使⽤Java-WebSocket库): 1、其实只需要掌握⼀个类,WebSocketClient即可 2、指定IP/域名和端⼝连接服务器,当服务器端有通知时会回调onMessage⽅法 3、然后调⽤connect⽅法进⾏连接 4、连接后就可以发送消息了,发送消息也很简单,除了⽀持String的发送还⽀持byte发送,好了,客户端就这么愉快的写完了(详细代码见后⾯打包的demo)。
⼆、服务端的创建: 1-1、Java Application服务端创建(使⽤Java-WebSocket库),其实也很简单,就继承⼀个类WebSocketServer: 1-2、然后在main⽅法中开启服务端,现在就可以⽤Android客户端来连接进⾏聊天、接收推送了,实在是太简单了。
2-1、Java Web(tomcat)服务端创建,这⾥不使⽤Java-WebSocket库,直接使⽤Java API javax.websocket包中的WebSocket相关类(注意Java API只实现了标准的RFC 6455(JSR256),如果你⾮要选择其它早期草案则需要⽤Java-WebSocket来实现,在Java-WebSocket中连接协议“Draft_17”就是标准的RFC 6455(JSR256),另外要使⽤Java API javax.websocket包中的WebSocket相关类要求JDK7及以上,Tomcat 7.0.49及以上): 2-2、然后启动tomcat就可以愉快的⽤Android客户端来连接进⾏聊天、接收推送了。
使用spring WebSocket还有一种方法进行推送,就是使用STOMP协议进行推送,其核心思
想就是订阅(subscribe)。
1. 配置Spring的Configuration文件。
注一:Application-destination-prefix:用例对URL进行区分,这里的”/app”表明,如果想要
使用这个message broker(消息代理),就需要在URL中添加”/app”。
注二:Stomp-endpoint:这里是一个stomp的一个借助WebSocket进行握手的配置。这个
握手的interceptor在这里什么都不需要做,我们不再需要session了。
注三:simple-broker:非常重要,在这里我们只使用一个simple broker,但是将来可以使
用一个更为复杂的broker(Apache ActiveMQ等)。可参考下图理解simple broker的作用。
2. 实现一个HandshakeInterceptor(简单到没有)
3. 我们可以写一个Controller用于管理这些“/app”请求。
这里的@MessageMapping(“/greeting”),将用来处理“/app/greeting”的STOMP的SEND请
求。
这里的@SendTo(“/topic/show”),将所有订阅了(subscribe)“/topic/show”)的用户进行消息
的推送,推送的内容就是函数的返回值”[hello]”。
这里的@SubscribeMapping(“/init/{id}”),一个新的订阅,这个订阅不是simple broker,但
是也可以返回一个JSON的字符串。
4. 开始编写web页面(使用jQuery)。
建立STOMP连接,之前要进行websocket连接(握手)。
订阅”/topic/show”
请求向所有订阅过”/topic/show”的client推送消息