长链接 Socket.IO

概念

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

短链接与长链接

通俗来说,浏览器和服务器每进行一次通讯,就创建一次链接,任务结束就中断链接,即短链接。相反地,假如通讯结束(如完成了某个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字符串。android

// 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];
  }
});

提供了以下的选项能够设置:git

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

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

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

你能够获得一个回调来确认服务器收到一个消息:json

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

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

// 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参数)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);
      }
    });
  }
});
相关文章
相关标签/搜索