zoukankan      html  css  js  c++  java
  • 长连接 Socket.IO

    概念

    说到长连接,对应的就是短连接了。下面先说明一下长连接和短连接的区别:

    短连接与长连接

    通俗来讲,浏览器和服务器每进行一次通信,就建立一次连接,任务结束就中断连接,即短连接。相反地,假如通信结束(如完成了某个HTML文件的信息获取)后保持连接则为长连接。在HTTP/1.0中,默认使用短连接。从HTTP/1.1起,默认使用长连接,这样做的优点是显而易见的,一个网页的加载可能需要HTML文件和多个CSS或者JS,假如每获取一个静态文件都建立一次连接,那么就太浪费时间了,而在保持连接的情况下,继续GET即可。
    对于频繁请求资源的客户来说,较适用长连接。但连接数最好进行限制,防止建立太多连接拖累服务端。一般浏览器对一个网站的连接是有限制的几个,所以网站会将资源部署在多个域名上以实现浏览器同时请求。
    短/长连接应当在TCP连接的范畴中来讨论。有人常说HTTP的短连接和长连接如何如何,但是HTTP只是一个应用层协议,又是无状态的,最终实质性的保持连接还是得靠传输层,即TCP。

    keep-alive

    我们使用浏览器的开发者工具查看网络请求和响应信息时经常在HTTP请求头部看到Connection: keep-alive,一般的浏览器都会带着个头去请求数据,假如有特殊需求可以用Connection: close断开。HTTP头部的Connection也不一定就被客户端或服务端老老实实地遵循,毕竟各有各的考虑,尤其是在HTTP/1.0这还只是个实验性的功能,而在HTTP/1.1默认长连接于是没有对长连接做特殊的规定。长连接也不能无限期地长,服务端有可能在头部放Keep-Alive,其中timeout等于一个值来规定保持连接的秒数,还可以用max来规定多少次请求后断开。如果没有说明怎么断开,主动发起四次握手也可以实现连接的断开。
    HTTP的keep-alive与TCP的keep-alive到底是什么关系? 答:TCP的keep alive是检查当前TCP连接是否活着;HTTP的Keep-alive是要让一个TCP连接活久点

    Socket.IO

    该项目是从JavaScript迁移过来的。demo项目地址:Android chat demo
    在Android Studio里面引入Socket.IO,在build.gradle里面加入:
    compile ('io.socket:socket.io-client:0.8.3') {
      // excluding org.json which is provided by Android
      exclude group: 'org.json', module: 'json'
    }

    使用Socket.IO

    Socket.IO-client 基本上和JS版本有相同的API,你使用IO.socket()来初始化Socket。
    socket = IO.socket("http://localhost");  // 创建Socket.IO长连接对象
    socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
    
      @Override
      public void call(Object... args) {
        socket.emit("foo", "hi");
        socket.disconnect();
      }
    
    }).on("event", new Emitter.Listener() {
    
      @Override
      public void call(Object... args) {}
    
    }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
    
      @Override
      public void call(Object... args) {}
    
    }); // 注册事件监听对象 各种Event
    socket.connect();  // 连接socket

    这个库使用org.json来解析和组成JSON字符串。

    // Sending an object
    JSONObject obj = new JSONObject();
    obj.put("hello", "server");
    obj.put("binary", new byte[42]);
    socket.emit("foo", obj);
    
    // Receiving an object
    socket.on("foo", new Emitter.Listener() {
      @Override
      public void call(Object... args) {
        JSONObject obj = (JSONObject)args[0];
      }
    });

    提供了如下的选项可以设置:

    IO.Options opts = new IO.Options();
    opts.forceNew = true;
    opts.reconnection = false;
    socket = IO.socket("http://localhost", opts);

    你可以使用这些参数来配置选项。注:如果你不想重用缓存的socket实例来查询参数变化时,你应该使用forceNew选项。如果你的程序想要登出一个用户,再登录一个新用户的时候可以使用这种方式:

    IO.Options opts = new IO.Options();
    opts.forceNew = true;
    opts.query = "auth_token=" + authToken;
    Socket socket = IO.socket("http://localhost", opts);

    你可以得到一个回调来确认服务器收到一个消息:

    socket.emit("foo", "woot", new Ack() {
      @Override
      public void call(Object... args) {}
    });

    反过来,你也可以发送一个确认消息,告诉服务器你收到了一个消息:

    // ack from client to server
    socket.on("foo", new Emitter.Listener() {
      @Override
      public void call(Object... args) {
        Ack ack = (Ack) args[args.length - 1];
        ack.call();
      }
    });

    你能够使用SSL(HTTPS、WSS)的设置:

    // default settings for all sockets
    IO.setDefaultSSLContext(mySSLContext);
    IO.setDefaultHostnameVerifier(myHostnameVerifier);
    
    // set as an option
    opts = new IO.Options();
    opts.sslContext = mySSLContext;
    opts.hostnameVerifier = myHostnameVerifier;
    socket = IO.socket("https://localhost", opts);

    查询更多Java文档可以查看:

    http://socketio.github.io/socket.io-client-java/apidocs/

    使用Transports访问Http头:(不常用,一般用来设置Cookie参数)

    // Called upon transport creation.
    socket.io().on(Manager.EVENT_TRANSPORT, new Emitter.Listener() {
      @Override
      public void call(Object... args) {
        Transport transport = (Transport)args[0];
    
        transport.on(Transport.EVENT_REQUEST_HEADERS, new Emitter.Listener() {
          @Override
          public void call(Object... args) {
            @SuppressWarnings("unchecked")
            Map<String, List<String>> headers = (Map<String, List<String>>)args[0];
            // modify request headers
            headers.put("Cookie", Arrays.asList("foo=1;"));
          }
        });
    
        transport.on(Transport.EVENT_RESPONSE_HEADERS, new Emitter.Listener() {
          @Override
          public void call(Object... args) {
            @SuppressWarnings("unchecked")
            Map<String, List<String>> headers = (Map<String, List<String>>)args[0];
            // access response headers
            String cookie = headers.get("Set-Cookie").get(0);
          }
        });
      }
    });
  • 相关阅读:
    @Autowired和@Resource注解的注入顺序
    八大排序算法(Java实现)+ 自制动画
    一文秒杀三个经典面试求和问题
    这篇文章,或许对还在上学的你,有一些帮助
    得了,一文把前缀和给扒的干干净净了。
    BF,BM,KMP,就这?
    那个贼贵的比特币到底是什么原理?
    小样?别以为你穿了几个马甲就不认得你是二分法!
    面试前必知必会的二分查找及其变种
    Vue.js 官方示例初探
  • 原文地址:https://www.cnblogs.com/renhui/p/6544835.html
Copyright © 2011-2022 走看看