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.1Upgrade: websocketConnection: UpgradeHost: example.comOrigin: nullSec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==Sec-WebSocket-Version: 13
这段请求会告诉服务器即将切换到websocket协议,如果服务器支持的话,会返回如下信息
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=Sec-WebSocket-Origin: nullSec-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 Setconnections = new CopyOnWriteArraySet (); 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"%>Apache Tomcat WebSocket Examples: Chat
运行结果
一次打开两个窗口,用户依次为guest0, guest1
guest0:
guest1:
guest0退出:
原文链接地址: