zoukankan      html  css  js  c++  java
  • socketio server推送

       假设面试官问你:要把server端的数据时时显示在浏览器上怎么实现?我想有非常多人会回答使用Ajax技术定时去訪问一个资源,没错,使用Ajax的确能实现。但面试官要的绝对不是这个答案。

    由于使用Ajax频繁訪问给服务端造成太大的压力,所以在大部分情况下都是不取的。面试官想要的答案应该是将server端的数据推送至浏览器,这样仅仅须要保持一个长链接就能够了。

    socket.io就能实现数据的时时推送,socket.io(官网:http://socket.io/)是一个跨平台。多种连接方式自己主动切换时时引擎。要说明的是,socket.io.js仅仅能完毕client功能,还须要server端的实现才干真正完毕数据的推送。socket.io官方给出的样例服务端使用node.js实现,我想还有非常多人对node.js是陌生的(me too)。

    socket.io服务端实现能够有多种语言,应该说仅仅要能支持socket协议就能够。

    以下的样例将给出两个java语言的服务端实现及其使用演示样例。演示样例内容非常easy,就是在服务端随机产生一个坐标(包括x,y值),然后将其推送至浏览器并显示。我想会推送一个坐标值,推送其他数据应该也不是问题。


    第一种实现、netty-socketio,坐标为:com.corundumstudio.socketio:netty-socketio:1.7.3(gradle)。假设使用的是maven。则坐标为:


    <groupId>com.corundumstudio.socketio</groupId>
    <artifactId>netty-socketio</artifactId>
    <version>1.7.3</version>

    a.服务端代码:

    public class Server {
    	private static List<SocketIOClient> clients = new ArrayList<SocketIOClient>();//用于保存全部客户端
    
    	public static void main(String[] args) throws Exception {
    		Configuration configuration = new Configuration();
    		configuration.setHostname("127.0.0.1");//设置主机名
    		configuration.setPort(8082);//设置监听的port号
    		SocketIOServer server = new SocketIOServer(configuration);//依据配置创建服务器对象
    
    		server.addConnectListener(new ConnectListener() {//加入客户端连接监听器
    			@Override
    			public void onConnect(SocketIOClient client) {
    				System.out.println("connected:SessionId=" + client.getSessionId());	
    				clients.add(client);//保存客户端
    			}
    		});
    		
    		server.start();
    		System.out.println("server started");
    		Timer timer = new Timer();
    		timer.schedule(new TimerTask() {
    			@Override
    			public void run() {
    				Random random = new Random();
    				for(SocketIOClient client : clients) {
    					client.sendEvent("pushpoint", new Point(random.nextInt(100), random.nextInt(100)));//每隔一秒推送一次
    				}
    			}
    		}, 1000, 1000);
    		
    		Object object = new Object();
    		synchronized (object) {
    			object.wait();
    		}
    	}
    
    }

    b.Point类:

    public class Point {
    	private int x;
    	private int y;
    	
    	public Point(int x, int y) {
    		this.x = x;
    		this.y = y;
    	}
    	
    	//getter,setter
    }

    c.html页面:

    <!DOCTYPE html>
    <html>
    <head>
        <title>netty-socketio測试</title>
    	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
    	<script src="socket.io/socket.io-1.0.6.js"></script>
        <script src="jquery-1.7.2.min.js"></script>
    	<script>
    		$(function(){
    			var socket =  io.connect('http://127.0.0.1:8082');
    			//监听名为pushpoint的事件,这与服务端推送的那个事件名称必须一致
    			socket.on("pushpoint", function(data){
    				$('#x').text(data.x);
    				$('#y').text(data.y);
    			});
    		});
    		
    	</script>
    </head>
    
    <body>
    	
    	<div id="display" style="height:50px;background-color:grey;">
    		x=<span id="x">0</span>, y=<span id="y">0</span>
    	</div>
    
    </body>
    
    </html>

    另外一种实现、socketio-netty(上面一个是netty-socketio),这个实如今maven中央库中好像还没有,该项目托管在google code上,项目地址为:http://code.google.com/p/socketio-netty/。本人是把它下载下来后手动安装在私服上的。现已上传至:http://download.csdn.net/detail/xtayfjpk/9720229,可供下载。


    a.服务端代码:

    public class Server2 {
    	private static List<IOClient> clients = new ArrayList<IOClient>();
    
    	public static void main(String[] args) throws Exception {
    		SocketIOServer ioServer = new SocketIOServer(new IOHandlerAbs() {
    			
    			@Override
    			public void OnShutdown() {
    				System.out.println("shut down");				
    			}
    			
    			@Override
    			public void OnMessage(IOClient client, String eventName) {
    				System.out.println("receive message,eventName=" + eventName);
    			}
    			
    			@Override
    			public void OnDisconnect(IOClient client) {
    				System.out.println("disconnect");				
    				System.out.println("disconnect");				
    			}
    			
    			@Override
    			public void OnConnect(IOClient client) {
    				System.out.println("connect");
    				clients.add(client);
    			}
    		}, 8088);
    		
    		ioServer.start();
    		System.out.println("server started");
    		Timer timer = new Timer();
    		timer.schedule(new TimerTask() {
    			@Override
    			public void run() {
    				Random random = new Random();
    				String data = "{"x":" +random.nextInt(100)+ ","y":" +random.nextInt(100)+ "}";
    				BASE64Encoder encoder = new BASE64Encoder();
    				data = encoder.encode(data.getBytes());
    				for(IOClient client : clients) {
    					client.send(formatMessage(data));
    				}
    			}
    		}, 1000, 1000);
    		
    		Object object = new Object();
    		synchronized (object) {
    			object.wait();
    		}
    	}
    
    	private static String formatMessage(String data) {
    		return String.format(
                    "5:::{"%s":"%s","%s":["%s"]}",//socket.io字符串格式
                    "name",
                    "push",//事件名称
                    "args",
                    data//携带的数据
                    );
    	}
    }

    须要说明的是。该实现不能像上一个实现一样发送一个对象,仅仅能发送一个字符串,并且该字符串中还不能包括双引號(或许还有其他特殊字符)。

    而推送过程中我们使用的数据格式非常可能是JSON。那就肯定有双引號,所以这里採取的办法是对要发送的数据进行BASE64编码。然后在client解码回来得到我们想要的数据。

    b.html页面:

    <!DOCTYPE html>
    <html>
    <head>
        <title>socketio-netty測试</title>
    	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
    	<script src="socket.io/socket.io-0.9.6.js"></script>
    	<script src="crypto-js/core-min.js"></script>
    	<script src="crypto-js/enc-base64-min.js"></script>
    	<script src="crypto-js/enc-utf16-min.js"></script>
        <script src="jquery-1.7.2.min.js"></script>
    	<script>
    		$(function(){
    			var host = "http://127.0.0.1:8088";
    			var socket = null;
    			if(/MSIE (d+.d+);/.test(navigator.userAgent)){
    				if(/MSIE 10(.d+);/.test(navigator.userAgent)){
    					socket = io.connect(host);
    				}else{
    					socket = io.connect(host,{transports:['jsonp-polling']}); 
    				}
    			} else {
    				socket = io.connect(host,{transports:['websocket','flashsocket','htmlfile','xhr-polling','jsonp-polling']}); 
    			}
    
    			socket.on("push", function(data){
    				var words  = CryptoJS.enc.Base64.parse(data);
    				var point  = CryptoJS.enc.Utf8.stringify(words);
    				point = JSON.parse(point);
    				$('#x').text(point.x);
    				$('#y').text(point.y);
    			});
    		});
    		
    	</script>
    </head>
    
    <body>
    	
    	<div id="display" style="height:50px;background-color:grey;">
    		x=<span id="x">0</span>, y=<span id="y">0</span>
    	</div>
    
    </body>
    
    </html>

    第一个样例中实现的socket.io版本号为1.0.6。第二个使用的版本号为0.9.6。这两种服务端实现都是基于netty框架的,但个人认为还是第一种实现比較好用,省去了编码的过程,并且封装程度更高。

    演示样例代码project已托管在GitHub中,使用gradle进行构建,地址为:https://github.com/xtayfjpk/socketio-test


    仅仅要将其捡出就可以执行。

  • 相关阅读:
    读取组合单元格
    Spire.XLS:一款Excel处理神器
    linq
    LINQ语句中的.AsEnumerable() 和 .AsQueryable()的区别
    合并单元格
    web sec / ssd / sshd
    linux——cat之查看cpu信息、显示终端、校验内存.............
    MATLAB mcr lib的环境变量书写
    Linux查看库依赖方法
    判断当前所使用python的版本和来源
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6691451.html
Copyright © 2011-2022 走看看