socketio 服务器推送

ゝ一世哀愁。 2022-07-11 05:37 339阅读 0赞

如果面试官问你:要把服务器端的数据时时显示在浏览器上怎么实现?我想有很多人会回答使用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,则坐标为:

[html] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. <**groupId**>com.corundumstudio.socketio</**groupId**>
  2. <**artifactId**>netty-socketio</**artifactId**>
  3. <**version**>1.7.3</**version**>

a.服务端代码:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. public class Server {
  2. private static List clients = new ArrayList();//用于保存所有客户端
  3. public static void main(String[] args) throws Exception {
  4. Configuration configuration = new Configuration();
  5. configuration.setHostname(“127.0.0.1”);//设置主机名
  6. configuration.setPort(8082);//设置监听的端口号
  7. SocketIOServer server = new SocketIOServer(configuration);//根据配置创建服务器对象
  8. server.addConnectListener(new ConnectListener() { //添加客户端连接监听器
  9. @Override
  10. public void onConnect(SocketIOClient client) {
  11. System.out.println(“connected:SessionId=” + client.getSessionId());
  12. clients.add(client);//保存客户端
  13. }
  14. });
  15. server.start();
  16. System.out.println(“server started”);
  17. Timer timer = new Timer();
  18. timer.schedule(new TimerTask() {
  19. @Override
  20. public void run() {
  21. Random random = new Random();
  22. for(SocketIOClient client : clients) {
  23. client.sendEvent(“pushpoint”, new Point(random.nextInt(100), random.nextInt(100)));//每隔一秒推送一次
  24. }
  25. }
  26. }, 1000, 1000);
  27. Object object = new Object();
  28. synchronized (object) {
  29. object.wait();
  30. }
  31. }
  32. }

b.Point类:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. public class Point {
  2. private int x;
  3. private int y;
  4. public Point(int x, int y) {
  5. this.x = x;
  6. this.y = y;
  7. }
  8. //getter,setter
  9. }

c.html页面:

[html] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. <!DOCTYPE html>
  2. <**html**>
  3. <**head**>
  4. <**title**>netty-socketio测试</**title**>
  5. <**meta http-equiv=”Content-Type” content=”text/html;charset=UTF-8”/>**
  6. <**script src=”socket.io/socket.io-1.0.6.js”></script**>
  7. <**script src=”jquery-1.7.2.min.js”></script**>
  8. <**script**>
  9. $(function(){
  10. var socket = io.connect(‘http://127.0.0.1:8082‘);
  11. //监听名为pushpoint的事件,这与服务端推送的那个事件名称必须一致
  12. socket.on(“pushpoint”, function(data){
  13. $(‘#x’).text(data.x);
  14. $(‘#y’).text(data.y);
  15. });
  16. });
  17. </**script**>
  18. </**head**>
  19. <**body**>
  20. <**div id=”display” style=”height:50px;background-color:grey;”>**
  21. x=<**span id=”x”>0</span>, y=<**span id=”y”>0</**span**>
  22. </**div**>
  23. </**body**>
  24. </**html**>

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

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. public class Server2 {
  2. private static List clients = new ArrayList();
  3. public static void main(String[] args) throws Exception {
  4. SocketIOServer ioServer = new SocketIOServer(new IOHandlerAbs() {
  5. @Override
  6. public void OnShutdown() {
  7. System.out.println(“shut down”);
  8. }
  9. @Override
  10. public void OnMessage(IOClient client, String eventName) {
  11. System.out.println(“receive message,eventName=” + eventName);
  12. }
  13. @Override
  14. public void OnDisconnect(IOClient client) {
  15. System.out.println(“disconnect”);
  16. System.out.println(“disconnect”);
  17. }
  18. @Override
  19. public void OnConnect(IOClient client) {
  20. System.out.println(“connect”);
  21. clients.add(client);
  22. }
  23. }, 8088);
  24. ioServer.start();
  25. System.out.println(“server started”);
  26. Timer timer = new Timer();
  27. timer.schedule(new TimerTask() {
  28. @Override
  29. public void run() {
  30. Random random = new Random();
  31. String data = “{\“x\“:” +random.nextInt(100)+ “,\“y\“:” +random.nextInt(100)+ “}“;
  32. BASE64Encoder encoder = new BASE64Encoder();
  33. data = encoder.encode(data.getBytes());
  34. for(IOClient client : clients) {
  35. client.send(formatMessage(data));
  36. }
  37. }
  38. }, 1000, 1000);
  39. Object object = new Object();
  40. synchronized (object) {
  41. object.wait();
  42. }
  43. }
  44. private static String formatMessage(String data) {
  45. return String.format(
  46. “5:::{\“%s\“:\“%s\“,\“%s\“:[\“%s\“]}“,//socket.io字符串格式
  47. “name”,
  48. “push”,//事件名称
  49. “args”,
  50. data//携带的数据
  51. );
  52. }
  53. }

需要说明的是,该实现不能像上一个实现一样发送一个对象,只能发送一个字符串,而且该字符串中还不能包含双引号(也许还有其它特殊字符)。而推送过程中我们使用的数据格式很可能是JSON,那就肯定有双引号,所以这里采取的办法是对要发送的数据进行BASE64编码,然后在客户端解码回来得到我们想要的数据。

b.html页面:

[html] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. <!DOCTYPE html>
  2. <**html**>
  3. <**head**>
  4. <**title**>socketio-netty测试</**title**>
  5. <**meta http-equiv=”Content-Type” content=”text/html;charset=UTF-8”/>**
  6. <**script src=”socket.io/socket.io-0.9.6.js”></script**>
  7. <**script src=”crypto-js/core-min.js”></script**>
  8. <**script src=”crypto-js/enc-base64-min.js”></script**>
  9. <**script src=”crypto-js/enc-utf16-min.js”></script**>
  10. <**script src=”jquery-1.7.2.min.js”></script**>
  11. <**script**>
  12. $(function(){
  13. var host = “http://127.0.0.1:8088“;
  14. var socket = null;
  15. if(/MSIE (\d+.\d+);/.test(navigator.userAgent)){
  16. if(/MSIE 10(.\d+);/.test(navigator.userAgent)){
  17. socket = io.connect(host);
  18. }else{
  19. socket = io.connect(host,{transports:[‘jsonp-polling’]});
  20. }
  21. } else {
  22. socket = io.connect(host,{transports:[‘websocket’,’flashsocket’,’htmlfile’,’xhr-polling’,’jsonp-polling’]});
  23. }
  24. socket.on(“push”, function(data){
  25. var words = CryptoJS.enc.Base64.parse(data);
  26. var point = CryptoJS.enc.Utf8.stringify(words);
  27. point = JSON.parse(point);
  28. $(‘#x’).text(point.x);
  29. $(‘#y’).text(point.y);
  30. });
  31. });
  32. </**script**>
  33. </**head**>
  34. <**body**>
  35. <**div id=”display” style=”height:50px;background-color:grey;”>**
  36. x=<**span id=”x”>0</span>, y=<**span id=”y”>0</**span**>
  37. </**div**>
  38. </**body**>
  39. </**html**>

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

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

只要将其捡出即可运行。

原文地址:http://blog.csdn.net/xtayfjpk/article/details/40948409

发表评论

表情:
评论列表 (有 0 条评论,339人围观)

还没有评论,来说两句吧...

相关阅读

    相关 DWR的服务器

     在开始本节内容之前,先来了解一下什么是服务器推送技术和DWR的推送方式。 1.服务器推送技术和DWR的推送方式 传统模式的 Web 系统以客户端

    相关 socketio 服务器

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

    相关 socketio 服务器

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