長鏈接 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);
      }
    });
  }
});
相關文章
相關標籤/搜索