探索WebKit內核(三)------ WebSocket

WebSocket是HTML5的一個重要特性,能提供client和server的雙向通信,是很多WebAPP做網絡通信的首選,不過它在Android的WebKit中並不支持,也就造就了socket.io的流行。在我們雲OS中當然不能漏掉這個特性,我這周的任務就是要在雲OS的Webkit中支持websocket,以此讓WebApp能直接調用websocket API。

某些平臺的webkit(比如Android)不支持websocket並不是webkit沒管這塊,而是這一特性需要在各個平臺特有的網絡層中做porting。所以初步判斷只需要補全網絡層的讀寫即可。先看看源碼WebCore/Modules/websockets,和websocket相關的代碼都在這個文件夾中,其結構如下:


通過WebSocket.cpp, WebSocket.h和WebSocket.idl包裝websocket js API,所以在js中new WebSocket("...",...");時,反映到webkit就是:

WebSocket.cpp -> WebSocketChannel.cpp -> WebSocketFrame.cpp, WebSocketHandshake.cpp -> SocketStreamHandle

其中,WebSocket.cpp是JS API包裝,WebSocketChannel.cpp是channel的包裝,WebSocketFrame.cpp和WebSocketHandshake.cpp處理websocket的上層協議,SocketStreamHandle處理網絡流。當SocketStreamHandle讀到數據後,又通過:

SocketStreamHandle->SocketStreamHandleClient->WebSocketChannelClient

這樣的路徑把消息發送到JS中的onmessage的回調中,其中WebSocketChannel.cpp是SocketStreamHandleClient的實現,WebSocket.cpp是WebSocketChannelClient的實現,因此這麼看來WebSocket整個下層的結構和信息迴路就清楚了。

分析完webkit代碼後,會發現webkit已經把websocket的架子和協議都已做好,唯獨缺了SocketStreamHandle中數據的讀和寫,也證實了我開始的判斷。看SocketStreamHandleBase.h和SocketStreamHandleBase.cpp會發現,只需要繼承SocketStreamHandleBase並實現虛方法platformSend和platformClose,另外讀到數據後調用SocketStreamHandleClient.didReceiveSocketStreamData把數據發送上層,這樣整個websocket就完整了。

實現這幾個方法並不困難,需要關注的是這裏需要基於異步的網絡讀寫,功底好的可以直接epoll或者select,如果新手或者有跨平臺的需求,可以用libevent,我就是使用了這個庫,具體代碼就不貼了,標準libevent讀和寫足矣。

補全websocket後,不但可以在JS API中提供websocket支持,也可以在native端提供websocket client端的能力,和js不同的是,native沒有js的執行環境,也不需要WebSocket.cpp的包裝,所以應該直接從WebSocketChannel.cpp開始用起,比如:

    RefPtr<WebSocketChannel> wsChannel = WebSocketChannel::create(page->mainFrame()->document(), channel);
    KURL url = KURL(KURL(), String("ws://127.0.0.1:9223"));
    wsChannel->connect(url, String("webkit"));
這裏的channel是WebSocketChannelClient的一個實現,在js環境是這個實現是WebSocket.cpp,而在native端就需要我們單獨實現,重要的是實現didReceiveMessage方法,這是websocket協議解析後的message回調,這樣就相當於在js中使用onmessage方法了。

其他websocket的部分就不多提了,對協議有興趣的朋友可以重點看WebSocketFrame.cpp和WebSocketHandshake.cpp,對webkit idl感興趣的可以看WebSocket.cpp, WebSocket.h和WebSocket.idl。總之,小小的websocket還是有很多幹貨的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章