Tomcat實(shí)現(xiàn)WebSocket的方法
WebSocket協(xié)議屬于HTML5標(biāo)準(zhǔn),越來越多瀏覽器已經(jīng)原生支持WebSocket,它能讓客戶端和服務(wù)端實(shí)現(xiàn)雙向通信。在客戶端和服務(wù)器端建立一條WebSocket連接后,服務(wù)器端消息可直接發(fā)送到客戶端,從而打破傳統(tǒng)的請(qǐng)求響應(yīng)模式,避免了無意義的請(qǐng)求。比如傳統(tǒng)的方式可能會(huì)使用AJAX不斷請(qǐng)求服務(wù)器端,而WebSocket則可以直接發(fā)送數(shù)據(jù)到客戶端且客戶端不必請(qǐng)求。同時(shí),由于有了瀏覽器的原生支持,編寫客戶端應(yīng)用程序也變得更加便捷且不必依賴第三方插件。另外,WebSocket協(xié)議摒棄了HTTP協(xié)議繁瑣的請(qǐng)求頭,而是以數(shù)據(jù)幀的方式進(jìn)行傳輸,效率更高。
圖為WebSocket協(xié)議通信的過程,首先客戶端會(huì)發(fā)送一個(gè)握手包告訴服務(wù)器端我想升級(jí)成WebSocket,不知道你服務(wù)器端是否同意,這時(shí)如果服務(wù)器端支持WebSocket協(xié)議則會(huì)返回一個(gè)握手包告訴客戶端沒問題,升級(jí)已確認(rèn)。然后就成功建立起了一條WebSocket連接,該連接支持雙向通信,并且使用WebSocket協(xié)議的數(shù)據(jù)幀格式發(fā)送消息。

握手過程需要說明下,為了讓W(xué)ebSocket協(xié)議能和現(xiàn)有HTTP協(xié)議Web架構(gòu)互相兼容,所以WebSocket協(xié)議的握手要基于HTTP協(xié)議,比如客戶端會(huì)發(fā)送類似如下的HTTP報(bào)文到服務(wù)器端請(qǐng)求升級(jí)為WebSocket協(xié)議,其中包含的Upgrade: websocket就是告訴服務(wù)器端我想升級(jí)協(xié)議:
GET ws://localhost:8080/hello HTTP/1.1 Origin: http://localhost:8080 Connection: Upgrade Host: localhost:8080 Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw== Upgrade: websocket Sec-WebSocket-Version: 13
此時(shí)如果服務(wù)器端支持WebSocket協(xié)議,則它會(huì)發(fā)送一個(gè)同意客戶端升級(jí)協(xié)議的報(bào)文,具體報(bào)文類似如下,其中Upgrade: websocket就是告訴客戶端我同意你升級(jí)協(xié)議:
HTTP/1.1 101 WebSocket Protocol Handshake Date: Fri, 10 Feb 2016 17:38:18 GMT Connection: Upgrade Server: Kaazing Gateway Upgrade: WebSocket Sec-WebSocket-Accept: rLHCkw/SKsO9GAH/ZSFhBATDKrU=
完成如上握手后,HTTP協(xié)議連接就被打破,接下去則是開始使用WebSocket協(xié)議進(jìn)行雙方通信,這條連接還是原來的那條TCP/IP連接,端口也還是原來的80或443。
下面舉一個(gè)Tomcat中編寫WebSocket的簡(jiǎn)單例子:
public class HelloWebSocketServlet extends WebSocketServlet {
private static List<MessageInbound> socketList = new ArrayList<MessageInbound>();
protected StreamInbound createWebSocketInbound(String subProtocol,HttpServletRequest request){
return new WebSocketMessageInbound();
}
public class WebSocketMessageInbound extends MessageInbound{
protected void onClose(int status){
super.onClose(status);
socketList.remove(this);
}
protected void onOpen(WsOutbound outbound){
super.onOpen(outbound);
socketList.add(this);
}
@Override
protected void onBinaryMessage(ByteBuffer message) throws IOException {
}
@Override
protected void onTextMessage(CharBuffer message) throws IOException {
for(MessageInbound messageInbound : socketList){
CharBuffer buffer = CharBuffer.wrap(message);
WsOutbound outbound = messageInbound.getWsOutbound();
outbound.writeTextMessage(buffer);
outbound.flush();
}
}
}
}
這個(gè)Servlet必須要繼承WebSocketServlet,接著創(chuàng)建一個(gè)繼承MessageInbound的WebSocketMessageInbound類,在該類中填充onClose、onOpen、onBinaryMessage和onTextMessage等方法即可完成各個(gè)事件的邏輯,其中onOpen會(huì)在一個(gè)WebSocket連接建立時(shí)被調(diào)用,onClose會(huì)在一個(gè)WebSocket關(guān)閉時(shí)被調(diào)用,onBinaryMessage則是Binary方式下接收到客戶端數(shù)據(jù)時(shí)被調(diào)用,onTextMessage則是Text方式下接收到客戶端數(shù)據(jù)時(shí)被調(diào)用。上面一段代碼實(shí)現(xiàn)了一個(gè)廣播的效果。
按照上面的處理邏輯,Tomcat對(duì)WebSocket的集成就不會(huì)太難了,就是在處理請(qǐng)求時(shí)如果遇到WebSocket協(xié)議請(qǐng)求則做特殊處理,保持住連接并在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用WebSocketServlet的MessageInbound的onClose、onOpen、onBinaryMessage和onTextMessage等方法。由于WebSocket一般建議在NIO模式下使用,所以看看NIO模式集成WebSocket協(xié)議。
如圖,對(duì)于WebSocket的客戶端連接被接收器接收后注冊(cè)到NioChannel隊(duì)列中,Poller組件不斷輪休是否有NioChannel需要處理,如果有則經(jīng)過處理管道后進(jìn)到繼承了WebSocketServlet的Servlet上,WebSocketServlet的doGet方法會(huì)處理WebSocket握手,告訴返回客戶端同意升級(jí)協(xié)議。往后Poller繼續(xù)不斷輪休相關(guān)NioChannel,一旦發(fā)現(xiàn)是使用WebSocket協(xié)議的管道則會(huì)調(diào)用MessageInbound的相關(guān)方法,完成不同事件的處理,從而實(shí)現(xiàn)對(duì)WebSocket協(xié)議的支持。

相關(guān)文章
Tomcat啟動(dòng)時(shí)如何設(shè)置JVM參數(shù)
這篇文章主要介紹了Tomcat啟動(dòng)時(shí)如何設(shè)置JVM參數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
Tomcat監(jiān)測(cè)腳本的實(shí)現(xiàn)示例
這篇文章主要給大家介紹了Tomcat監(jiān)測(cè)腳本的實(shí)現(xiàn)方法,文中給出了詳細(xì)的示例代碼和介紹,對(duì)大家具有一定的參考價(jià)值,有需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)把。2017-01-01
詳解tomcat 解決 POST請(qǐng)求傳參數(shù)過長受限制的問題
這篇文章主要介紹了詳解tomcat 解決 POST請(qǐng)求傳參數(shù)過長受限制的問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
tomcat如何去掉項(xiàng)目名稱直接訪問項(xiàng)目
這篇文章主要介紹了tomcat如何去掉項(xiàng)目名稱直接訪問項(xiàng)目問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
騰訊云申請(qǐng)免費(fèi)ssl證書配置tomcat使http變https
這篇文章主要介紹了騰訊云申請(qǐng)免費(fèi)ssl證書配置tomcat使http變https,詳細(xì)的介紹了每個(gè)步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06
讓IIS6支持JSP的設(shè)置方法(IIS完美整合Tomcat)
這方面的教程網(wǎng)上很多,多數(shù)是copy之后又copy,以至于有些細(xì)節(jié)一直含糊不清,也導(dǎo)致我走了許多彎路,今天腳本之家小編特為大家整理了一些方法,經(jīng)測(cè)試正常運(yùn)行jsp2014-07-07

