websocket即時通信

websocket 通信

一.先說說WEB即時通信技術

一般通過兩種方式來實現Web實時用:
1.輪詢機制
(輪詢):這是最早的一種實現實時 Web 應用的方案。客戶端以一定的時間間隔向服務端發出請求,以頻繁請求的方式來保持客戶端和服務器端的同步。這種同步方案的缺點是,當客戶端以固定頻率向服務 器發起請求的時候,服務器端的數據可能並沒有更新,這樣會帶來很多無謂的網絡傳輸,所以這是一種非常低效的實時方案

(Comet的長輪詢):是對定時輪詢的改進和提高,目地是爲了降低無效的網絡傳輸。當服務器端沒有數據更新的時候,連接會保持一段時間週期直到數據或狀態改變或者 時間過期,通過這種機制來減少無效的客戶端和服務器間的交互。當然,如果服務端的數據變更非常頻繁的話,這種機制和定時輪詢比較起來沒有本質上的性能的提 高

2.流技術
    常就是在客戶端的頁面使用一個隱藏的窗口向服務端發出一個長連接的請求。服務器端接到這個請求後作出迴應並不斷更新連接狀態以保證客戶端和服務 器端的連接不過期。通過這種機制可以將服務器端的信息源源不斷地推向客戶端。這種機制在用戶體驗上有一點問題,需要針對不同的瀏覽器設計不同的方案來改進 用戶體驗,同時這種機制在併發比較大的情況下,對服務器端的資源是一個極大的考驗。

    WebSocket 協議本質上是一個基於 TCP 的協議。爲了建立一個 WebSocket 連接,客戶端瀏覽器首先要向服務器發起一個 HTTP 請求,這個請求和通常的 HTTP 請求不同,包含了一些附加頭信息,其中附加頭信息”Upgrade: WebSocket”表明這是一個申請協議升級的 HTTP 請求,服務器端解析這些附加的頭信息然後產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket 連接就建立起來了,雙方就可以通過這個連接通道自由的傳遞信息,並且這個連接會持續存在直到客戶端或者服務器端的某一方主動的關閉連接。

二.搭建過程:

需要下載:websocket-api.jar包,這裏需要注意了,在高版本的Tomcat中,已經自帶這個jar包了(Tomcat7.0.70以上都有)。

1.新建一個WebSocketTest的類通過@ServerEndpoint(value="/websocketTest")
該註解用來指定一個URI,客戶端可以通過這個URI來連接到WebSocket。

2.通過在某個方法上加上@OnOpen註解,表明連接建立成功調用該方法
可選參數:(javax.websocket.Session session)
session爲與某個客戶端的連接會話,需要通過它來給客戶端發送數據

3.在某個方法上加上@OnMessage註解,表明收到客戶端消息後調用該方法
參數爲:(String message, javax.websocket.Session session)
message爲客戶端發送過來的消息,session爲可選的參數

4.在某個方法上加上@onClose()註解,表明連接關閉調用該方法

5.在某個方法上加上@OnError註解,表明發生錯誤時調用該方法
參數爲(Session session,Throwable error)

這樣大致的服務端就完成了

頁面上連接服務器是通過js來操作的:
var webSocket = new WebSocket('ws://<%=websocketurl%>/websocketTest');
webSocket.onerror = function(event) {
onError(event)
};

webSocket.onopen = function(event) {
onOpen(event)
};

webSocket.onmessage = function(event) {
onMessage(event)
};

function onMessage(event) {
document.getElementById('messages').innerHTML += '<br />'+ event.data;
}

function onOpen(event) {
document.getElementById('messages').innerHTML = 'webSocket 連接建立成功!';
}

function onError(event) {
alert(event.data);
}

function sendMsg(){
for(var i=0;i<1;i++){
webSocket.send(document.getElementById('sendPeople').value+"*"+document.getElementById('sendContent').value);
}
document.getElementById('sendContent').value="";
return false;
}

這樣就實現了websocket的通信了,可以主動向瀏覽器進行推送消息,由於websocket是基於HTHL5開發的,所以低版本的IE就不支持了。

最後提一下,websocket中有自己的session,這與HttpSession是不一樣的,那麼我們應該怎樣通過websocket的session來獲取HttpSession呢?這裏源碼中也寫好了,網上教程也很多,就說一下最普遍的方法:

1.建一個GetHttpSessionConfigurator類並繼承Configurator類
代碼如下:

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
/*
 * 獲取HttpSession
 * 
 */
public class GetHttpSessionConfigurator extends Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession=(HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}


2.在@ServerEndpoint 註解裏面添加 configurator 屬性
如:@ServerEndpoint(value="/websocketTest",configurator=GetHttpSessionConfigurator.class)

3.在onOpen方法里加入參數EndpointConfig config即可獲取HttpSession
如:HttpSession httpsession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());

以上三步即可解決session轉化的問題!



三.效果圖


1.指向性單對單聊天效果圖:



2.三人聊天效果圖:



四.遇到的錯誤

在這裏也遇到了一個錯誤,可能也是比較常見的,給大家說一下:
開始時我用Myeclipse新建了一個項目(jdk1.7,tomcat6.0的libraries運行環境),在運行時我用了tomcat7.0,於是瀏覽器會提示failed: Error during WebSocket handshake: Unexpected response code: 404,很納悶,找不到地址,怎麼可能呢?,搜了一些帖子隱約得的發現一些問題,我更換了運行環境,將tomcat6.0的libraries更換爲tomcat8.0的,沒有手動加入websocket-api.jar包,項目沒有報錯,於是看了看發現tomcat8.0的libraries含有websocket-api.jar包,並且用tomcat8.0進行運行,完全正常了,後來分析了一下發現這種錯誤就是jar包衝突導致的。



這裏附上源碼鏈接:http://download.csdn.net/detail/qq_27063119/9747437


網上的這位仁兄寫的比較好,簡單易懂,推薦看看   http://blog.chenzuhuang.com/archive/28.html

發佈了48 篇原創文章 · 獲贊 74 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章