socketio 服务器推送

 

 

   如果面试官问你:要把服务器端的数据时时显示在浏览器上怎么实现?我想有很多人会回答使用Ajax技术定时去访问一个资源,没错,使用Ajax的确能实现,但面试官要的绝对不是这个答案。因为使用Ajax频繁访问给服务端造成太大的压力,所以在大部分情况下都是不取的。面试官想要的答案应该是将服务器端的数据推送至浏览器,这样只需要保持一个长链接就可以了。

 

 

socket.io就能实现数据的时时推送,socket.io(官网:http://socket.io/)是一个跨平台,多种连接方式自动切换时时引擎。要说明的是,socket.io.js只能完成客户端功能,还需要服务器端的实现才能真正完成数据的推送。socket.io官方给出的例子服务端使用node.js实现,我想还有很多人对node.js是陌生的(me too)。socket.io服务端实现可以有多种语言,应该说只要能支持socket协议就可以。

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

 

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

 

com.corundumstudio.socketio
netty-socketio
1.7.3


a.服务端代码:

 

 

public class Server {
	private static List clients = new ArrayList();//用于保存所有客户端

	public static void main(String[] args) throws Exception {
		Configuration configuration = new Configuration();
		configuration.setHostname("127.0.0.1");//设置主机名
		configuration.setPort(8082);//设置监听的端口号
		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页面:

 

 




    netty-socketio测试
	
	
    
	



	
	
x=0, y=0


第二种实现、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 clients = new ArrayList();

	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");							
			}
			
			@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编码,然后在客户端解码回来得到我们想要的数据。

 

b.html页面:

 




    socketio-netty测试
	
	
	
	
	
    
	



	
	
x=0, y=0


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

 

 

 

示例代码工程已托管在GitHub中,使用gradle进行构建,地址为:https://github.com/xtayfjpk/socketio-test。
只要将其检出即可运行。

你可能感兴趣的:(java相关)