- package com.solin.chat;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- 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;
- /**
- * JSR356实现WebSocket有两种方式,一种是使用注解的,另一种是继承javax.websocket.Endpoint类,
- * 推荐方式是使用注解(本例使用注解)
- *
- * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
- * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
- */
- @ServerEndpoint("/websocket")
- public class WebSocketTest {
- //连接池,用来保存每个客户端连接的对象
- private static List<WebSocketTest> msgList
- = new ArrayList<WebSocketTest>();
- //与某个客户端的连接会话,需要通过它来给客户端发送数据
- private Session session;
- /**
- * 连接建立成功调用的方法
- * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
- */
- @OnOpen
- public void onOpen(Session session){
- this.session = session;
- msgList.add(this);
- System.out.println("有新连接加入");
- }
- /**
- * 连接关闭调用的方法
- */
- @OnClose
- public void onClose(){
- msgList.remove(this);
- System.out.println("有连接关闭");
- }
- /**
- * 收到客户端消息后调用的方法
- * @param message 客户端发送过来的消息
- * @param session 可选的参数
- */
- @OnMessage
- public void onMessage(String message, Session session) {
- System.out.println("来自客户端的消息:" + message);
- //群发消息
- for(WebSocketTest item: msgList){
- try {
- item.sendMessage(message);
- } catch (IOException e) {
- e.printStackTrace();
- continue;
- }
- }
- }
- /**
- * 发生错误时调用
- * @param session
- * @param error
- */
- @OnError
- public void onError(Session session, Throwable error){
- System.out.println("发生错误");
- error.printStackTrace();
- }
- /**
- * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
- * @param message
- * @throws IOException
- */
- public void sendMessage(String message) throws IOException{
- this.session.getBasicRemote().sendText(message);//发送消息给客户端
- //this.session.getAsyncRemote().sendText(message);
- }
- }
WebSocket客户端
index.jsp- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>基于Java服务器端的消息主动推送技术揭秘</title>
- <style type="text/css">
- *{
- margin:0;
- padding:0;
- }
- body{background:#e2e2e2;}
- .chatBox{
- width:680px;
- margin:0 auto;
- text-align:center;
- }
- .chatBox h1{
- font-size:30px;
- color:#D29575;
- margin-top:20px;
- }
- .tipBox{
- text-align:left;
- line-height:35px;
- }
- .inputText{height:30px;}
- .chatContainer{
- width:100%;
- height:300px;
- overflow:hidden;
- text-align:left;
- border:1px solid #000;
- }
- .sendBox{text-align:left;}
- button{
- height:30px;
- width:80px;
- color:#fff;
- font-size:20px;
- background:#2996A1;
- margin:7px auto;
- cursor:pointer;
- outline:none;
- }
- </style>
- <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
- <script type="text/javascript">
- var ws;
- var socketCreated = false;
- var isLogout = false;
- //页面一加载就执行
- $(function(){
- $("#sendBox").hide();
- //判断浏览器是否支持WebSocket
- if(window.WebSocket || window.MozWebSocket){
- $("#chatContainer").append("<span style='color:green;'>您的浏览器支持WebSocket,您可以尝试连接到聊天服务器!</span><br/>");
- $("#conUrl").val("localhost:8080/Solin_Chat/webChat");
- }else{
- $("#chatContainer").append("<span style='color:red;'>浏览器不支持WebSocket,请更换浏览器!</span><br/>");
- }
- //绑定消息发送事件
- $("#sendMsgBtn").click(function(){
- var msg = $("#msgContent").val().trim();
- if(msg != ""){
- ws.send($("#loginUser").val()+"说:"+msg+"<br/>");
- }
- $("#msgContent").val("");
- });
- //给连接按钮绑定点击事件
- $("#conBtn").click(function(){
- //0:正在连接 1:已连接 2:正在关闭连接 3:已关闭连接
- if(socketCreated && (ws.readyState == 0 || ws.readyState == 1)){//已经连接了
- ws.send("<span style='color:blue;font-weight:bold'>["+$("#loginUser").val()+"]离开了聊天室...</span><br/>")
- socketCreated = false;
- isLogout = true;
- ws.close();//关闭连接
- $("#conBtn").html("连接");//修改按钮文字
- $("#sendBox").hide();
- }else{//还没连接
- //申请WebSocket对象
- if("WebSocket" in window){
- ws = new WebSocket("ws://"+$("#conUrl").val());
- }else if("MozWebSocket" in window){
- ws = new MozWebSocket("ws://"+$("#conUrl").val());
- }
- socketCreated = true;
- isLogout = false;
- $("#conBtn").html("断开");//修改按钮文字
- //注册事件
- ws.onopen = wsOnOpen;//获得连接时
- ws.onmessage = wsOnMessage;//接收消息时
- ws.onclose = wsOnClose;//关闭连接时
- ws.onerror = wsOnError;//处理发生错误时(消息发送错误、连接错误)
- }
- });
- });
- function wsOnOpen(){
- ws.send("<span style='color:red;font-weight:bold'>["+$("#loginUser").val()+"]进入了聊天室...</span><br/>");
- $("#sendBox").show();
- }
- function wsOnMessage(event){
- $("#chatContainer").append(event.data);
- }
- function wsOnClose(){
- }
- function wsOnError(){
- $("#chatContainer").append("连接错误,请检查...<br/>");
- }
- </script>
- </head>
- <body>
- <div class="chatBox">
- <h1>基于Java服务器端的消息主动推送技术揭秘</h1>
- <div class="tipBox">
- 服务器地址:<input type="text" class="inputText" id="conUrl" style="width:315px;" />
- 用户名:<input type="text" class="inputText" id="loginUser" value="Solin" style="width:190px;" />
- <button type="button" id="conBtn">连接</button>
- </div>
- <div class="chatContainer" id="chatContainer"></div>
- <div class="sendBox" id="sendBox">
- <input type="text" class="inputText" style="width:588px;" id="msgContent" />
- <button type="button" id="sendMsgBtn">发送</button>
- </div>
- </div>
- </body>
- </html>
测试结果
1、什么是WebSocket?
WebSocket 是一种自然的全双工、双向、单套接字连接。使用WebSocket,你的HTTP 请求变成打开WebSocket 连接(WebSocket 或者WebSocket over TLS(TransportLayer Security,传输层安全性,原称“SSL”))的单一请求,并且重用从客户端到服务器以及服务器到客户端的同一连接。WebSocket 减少了延迟,因为一旦建立起WebSocket 连接,服务器可以在消息可用时发送它们。例如,和轮询不同,WebSocket只发出一个请求。服务器不需要等待来自客户端的请求。相似地,客户端可以在任何时候向服务器发送消息。相比轮询不管是否有可用消息,每隔一段时间都发送一个请求,单一请求大大减少了延迟。
2、WebSocket API
WebSocket API 使你可以通过Web,在客户端应用程序和服务器端进程之间建立全双工的双向通信。WebSocket 接口规定了可用于客户端的方法以及客户端与网络的交互方式。
3、WebSocket构造函数
为了建立到服务器的WebSocket连接,使用WebSocket接口,通过指向一个代表所要连接端点的URL,实例化一个WebSocket对象。WebSocket 协议定义了两种URL方案(URL scheme)—ws和wss,分别用于客户端和服务器之间的非加密与加密流量。
实例:var ws = new WebSocket("ws://www.websocket.org");
4、WebSocket事件
WebSocket API 是纯事件驱动的。应用程序代码监听WebSocket对象上的事件,以便处理输入数据和连接状态的改变。WebSocket协议也是事件驱动的。
WebSocket对象调度4个不同的事件:
A、open事件:
一旦服务器响应了WebSocket连接请求,open事件触发并建立一个连接。open事件对应的回调函数称作onopen
实例:
ws.onopen = function(e) {
console.log("Connection open...");
};
- 1
- 2
- 3
B、messagess事件:
message事件在接收到消息时触发,对应于该事件的回调函数是onmessage。
实例:
ws.onmessage = function(e) {
if(typeof e.data === "string"){
console.log("String message received", e, e.data);
} else {
console.log("Other message received", e, e.data);
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
C、error事件:
error 事件在响应意外故障的时候触发。与该事件对应的回调函数为onerror。
实例:
ws.onerror = function(e){
console.log('websocked error');
handerError();
}
- 1
- 2
- 3
- 4
D、close事件:
close 事件在WebSocket 连接关闭时触发。对应于close 事件的回调函数是onclose。
实例:
ws.onclose = function(e) {
console.log("Connection closed", e);
};
- 1
- 2
- 3
5、WebSocket方法
WebSocket 对象有两个方法:send() 和close()。
A、 send() 方法:
使用WebSocket在客户端和服务器之间建立全双工双向连接后,就可以在连接打开时调用send() 方法。使用send() 方法可以从客户端向服务器发送消息。在发送一条或者多条消息之后,可以保持连接打开,或者调用close() 方法终止连接。
实例:
ws.send("Hello WebSocket!");
- 1
B、close ()方法:
使用close()方法,可以关闭WebSocket连接或者终止连接尝试。如果连接已经关闭,该方法就什么都不做。在调用close()之后,不能在已经关闭的WebSocket上发送任何数据。可以向close()方法传递两个可选参数:code(数字型的状态代码)和reason(一个文本字符串)。传递这些参数能够向服务器传递关于客户关闭连接原因的信息。
注:以上是对 WebSocket的简单介绍,下面将用一个简单的网页实时聊天案例来介绍如何使用WebSocket