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...");
};
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);
}
};
c、error事件:
error 事件在响应意外故障的时候触发。与该事件对应的回调函数为onerror。
实例:
ws.onerror = function(e){
console.log('websocked error');
handererror();
}
d、close事件:
close 事件在websocket 连接关闭时触发。对应于close 事件的回调函数是onclose。
实例:
ws.onclose = function(e) {
console.log("connection closed", e);
};
5、websocket方法
websocket 对象有两个方法:send() 和close()。
a、 send() 方法:
使用websocket在客户端和服务器之间建立全双工双向连接后,就可以在连接打开时调用send() 方法。使用send() 方法可以从客户端向服务器发送消息。在发送一条或者多条消息之后,可以保持连接打开,或者调用close() 方法终止连接。
实例:
ws.send("hello websocket!");
b、close ()方法:
使用close()方法,可以关闭websocket连接或者终止连接尝试。如果连接已经关闭,该方法就什么都不做。在调用close()之后,不能在已经关闭的websocket上发送任何数据。可以向close()方法传递两个可选参数:code(数字型的状态代码)和reason(一个文本字符串)。传递这些参数能够向服务器传递关于客户关闭连接原因的信息。
注:以上是对 websocket的简单介绍,下面将用一个简单的网页实时聊天案例来介绍如何使用websocket
a:首先新建一个项目我这里叫chatroom,在建一个包然后新建一个类用于实现服务器端的连接我的类名叫chatwebsocketservlet.java;
具体项目搭建如下图:
b:写服务器端实现类chatwebsocketservlet.java,具体代码如下:
package com.yc.chat.servlet;
import java.io.ioexception;
import java.nio.bytebuffer;
import java.nio.charbuffer;
import java.text.simpledateformat;
import java.util.date;
import java.util.hashmap;
import java.util.map;
import java.util.set;
import javax.servlet.annotation.webservlet;
import javax.servlet.http.httpservletrequest;
import org.apache.catalina.websocket.messageinbound;
import org.apache.catalina.websocket.streaminbound;
import org.apache.catalina.websocket.websocketservlet;
import org.apache.catalina.websocket.wsoutbound;
@webservlet("/chat")
public class chatwebsocketservlet extends websocketservlet {
private final map<integer, wsoutbound> map = new hashmap<integer, wsoutbound>();
private static final long serialversionuid = -1058445282919079067l;
@override
protected streaminbound createwebsocketinbound(string arg0, httpservletrequest request) {
// streaminbound:基于流的websocket实现类(带内流),应用程序应当扩展这个类并实现其抽象方法onbinarydata和ontextdata。
return new chatmessageinbound();
}
class chatmessageinbound extends messageinbound {
// messageinbound:基于消息的websocket实现类(带内消息),应用程序应当扩展这个类并实现其抽象方法onbinarymessage和ontextmessage。
@override
protected void onopen(wsoutbound outbound) {
map.put(outbound.hashcode(), outbound);
super.onopen(outbound);
}
@override
protected void onclose(int status) {
map.remove(getwsoutbound().hashcode());
super.onclose(status);
}
@override
protected void onbinarymessage(bytebuffer buffer) throws ioexception {
}
@override
protected void ontextmessage(charbuffer buffer) throws ioexception {
string msg = buffer.tostring();
date date = new date();
simpledateformat sdf = new simpledateformat("hh:mm:ss");
msg = " <font color=green>匿名用戶 " + sdf.format(date) + "</font><br/> " + msg;
broadcast(msg);
}
private void broadcast(string msg) {
set<integer> set = map.keyset();
for (integer integer : set) {
wsoutbound outbound = map.get(integer);
charbuffer buffer = charbuffer.wrap(msg);
try {
outbound.writetextmessage(buffer);
outbound.flush();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
}
}
c:实现前台页面index.jsp(为了展示功能并没有美化,比较简陋)具体代码如下:
<%@ page language="java" contenttype="text/html; charset=utf-8"
pageencoding="utf-8"%>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>websocket聊天室</title>
<style type="text/css">
#chat {
text-align: left;
width: 600px;
height: 500px;
width: 600px;
}
#up {
text-align: left;
width: 100%;
height: 400px;
border: 1px solid green;
overflow-y: auto;
}
#down {
text-align: left;
height: 100px;
width: 100%;
}
</style>
</head>
<body>
<h2 align="center">基于html5的聊天室</h2>
<div align="center" style="width: 100%; height: 700px;">
<div id="chat">
<div id="up"></div>
<div id="down">
<textarea type="text" style="width: 602px; height: 100%;" id="send"></textarea>
</div>
</div>
<input type="button" value="连接" onclick="chat(this);"> <input
type="button" value="发送" onclick="send(this);" disabled="disabled"
id="send_btn" title="ctrl+enter发送">
</div>
</body>
<script type="text/javascript">
var socket;
var receive_text = document.getelementbyid("up");
var send_text = document.getelementbyid("send");
function addtext(msg) {
receive_text.innerhtml += "<br/>" + msg;
receive_text.scrolltop = receive_text.scrollheight;
}
var chat = function(obj) {
obj.disabled = "disabled";
socket = new websocket('ws://localhost:8080/chatroom/chat');
receive_text.innerhtml += "<font color=green>正在连接服务器……</font>";
//打开socket
socket.onopen = function(event) {
addtext("<font color=green>连接成功!</font>");
document.getelementbyid("send_btn").disabled = false;
send_text.focus();
document.onkeydown = function(event) {
if (event.keycode == 13 && event.ctrlkey) {
send();
}
}
};
socket.onmessage = function(event) {
addtext(event.data);
};
socket.onclose = function(event) {
addtext("<font color=red>连接断开!</font>");
obj.disabled = "";
};
if (socket == null) {
addtext("<font color=red>连接失败!</font>");
}
};
var send = function(obj) {
if (send_text.value == "") {
return;
}
socket.send(send_text.value);
send_text.value = "";
send_text.focus();
}
</script>
</html>
这样一个简单的实时聊天页面就做好了,接下来将项目部署到tomcat 7.0服务器,并开启服务器就可以实现聊天了
结果展示:
1.在地址栏输入服务器地址:
http://127.0.0.1:8080/chatroom/index.jsp
点击连接服务器结果如下:
2.分别在两个不同的浏览器打开并互相发送信息(我这里用谷歌和火狐)结果如下: