WebSocket是什么呢?
WebSocket一種在單個 TCP 連接上進行全雙工通訊的協議。WebSocket通信協議于2011年被IETF定為標準RFC 6455,并被RFC7936所補充規范,WebSocketAPI被W3C定為標準。
WebSocket 是獨立的、創建在 TCP 上的協議,和 HTTP 的唯一關聯是使用 HTTP 協議的101狀態碼進行協議切換,使用的 TCP 端口是80,可以用于繞過大多數防火墻的限制。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端直接向客戶端推送數據而不需要客戶端進行請求,在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并允許數據進行雙向傳送。
目前常見的瀏覽器如 Chrome、IE、Firefox、Safari、Opera 等都支持 WebSocket,同時需要服務端程序支持 WebSocket。
--------------------------------------------------------------------------------------
以上摘自wiki,總的來說websocket實現了服務器和瀏覽器之間的雙向通信,擺脫了以往的一問一答的通信方式,可以自由地傳輸數據.
Websocket有什么優點?
- 由于沒有http頭信息,所以傳輸的數據包很小
- 服務器可以主動推送信息
Websocket的握手協議
還是照搬wiki上的例子,websocket在建立連接時,瀏覽器會向服務器發出如下請求
GET / HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: example.com Origin: null Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== Sec-WebSocket-Version: 13
這段請求會告訴服務器即將切換到websocket協議,如果服務器支持的話,會返回如下信息
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= Sec-WebSocket-Origin: null Sec-WebSocket-Location: ws://example.com/
至此,握手階段完成,服務器和瀏覽器之間可以開始發送和接收信息
使用Websocket實現一個簡單的網頁聊天室
- 使用tomcat8的websocket-api
- 參考tomcat自帶的example
服務器端ChatServlet
package com.yc.chatroom; import java.io.IOException; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.annotation.WebServlet; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint(value="/websocket/chat")//指定客戶端連接地址 public class ChatServlet { private static final long serialVersionUID = 1L; private static final String GUEST_PREFIX = "Guest"; private static final AtomicInteger connectionIds = new AtomicInteger(0); private static final Set<ChatServlet> connections = new CopyOnWriteArraySet<ChatServlet>(); private final String nickname; private Session session; public ChatServlet() { nickname = GUEST_PREFIX + connectionIds.getAndIncrement(); } @OnOpen public void start(Session session) { this.session = session; connections.add(this); String message = String.format("* %s %s", nickname, "has joined."); broadcast(message); //廣播用戶加入消息 } @OnClose public void end() { connections.remove(this); String message = String.format("* %s %s", nickname, "has disconnected."); broadcast(message); //廣播用戶推出消息 } @OnMessage public void incoming(String message) { // Never trust the client String filteredMessage = String.format("%s: %s", nickname, message.toString()); broadcast(filteredMessage); //廣播發送內容 } @OnError public void onError(Throwable t) throws Throwable { t.printStackTrace(); } private static void broadcast(String msg) { for (ChatServlet client : connections) { try { synchronized (client) { client.session.getBasicRemote().sendText(msg);//給每個人發送消息 } } catch (IOException e) { connections.remove(client); try { client.session.close(); } catch (IOException e1) { // Ignore } String message = String.format("* %s %s", client.nickname, "has been disconnected."); broadcast(message); } } } }
瀏覽器端index.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <title>Apache Tomcat WebSocket Examples: Chat</title> <style type="text/css"> input#chat { width: 410px } #console-container { width: 400px; } #console { border: 1px solid #CCCCCC; border-right-color: #999999; border-bottom-color: #999999; height: 170px; overflow-y: scroll; padding: 5px; width: 100%; } #console p { padding: 0; margin: 0; } </style> </head> <body> <div> <p> <input type="text" placeholder="type and press enter to chat" id="chat" /> </p> <div id="console-container"> <div id="console"></div> </div> </div> </body> <script type="text/javascript"> /** * 指定要連接的websocket地址 * 如果使用https,則使用wss:// **/ var socket = new WebSocket('ws://' + window.location.host+ '/chatroom/websocket/chat'); //連接與服務器的連接 socket.onopen = function() { showMsg('Info: WebSocket connection opened.'); document.getElementById('chat').onkeydown = function(event) { if (event.keyCode == 13) { sendMsg(); } }; }; //斷開與服務器的連接 socket.onclose = function() { document.getElementById('chat').onkeydown = null; showMsg('Info: WebSocket closed.'); }; //與服務器之間的通信 socket.onmessage = function(message) { showMsg(message.data); }; //顯示消息 function showMsg(message) { var console = document.getElementById('console'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.innerHTML = message; console.appendChild(p); while (console.childNodes.length > 25) { console.removeChild(console.firstChild); } console.scrollTop = console.scrollHeight; } //發送消息 function sendMsg() { var message = document.getElementById('chat').value; if (message != '') { socket.send(message); document.getElementById('chat').value = ''; } } </script>
運行結果
一次打開兩個窗口,用戶依次為guest0, guest1
guest0:
guest1:
guest0退出:
原文鏈接地址:https://mssora.com/websocket-intro-and-chatroom/
文章列表
留言列表