WebSocket + html 实现聊天室
现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏览器需要不断的向服务器发出请求,然而HTTP request 的header是非常长的,里面包含的有用数据可能只是一个很小的值,这样会占用很多的带宽。
而比较新的技术去做轮询的效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。
在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此WebSocket 协议中,为我们实现即时服务带来了两大好处:
- Header
互相沟通的Header是很小的-大概只有 2 Bytes - Server Push
服务器的推送,服务器不再被动的接收到浏览器的request之后才返回数据,而是在有新数据时就主动推送给浏览器。
注意
WebSocket支持tomcat7,jdk1.7及其以上版本。
聊天室原理:
多个客户端和服务端进行握手,客户端将信息发送给服务端,有服务端通过广播的形式发送给大家。
聊天室效果图
目录
主要代码
ChatSocket.java
package com.xzy.socket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.xzy.vo.Message;
@ServerEndpoint("/chatSocket")
public class ChatSocket {
//存储当前socket对象
private static Set<ChatSocket> sockets = new HashSet<ChatSocket>();
//用户名
private static List<String> names = new ArrayList<String>();
private Session session;
private String username;
private Gson gson = new Gson();
// 进入
@OnOpen
public void open(Session session) {
this.session = session;
sockets.add(this);
String queryString = session.getQueryString();
this.username = queryString.substring(queryString.indexOf("=") + 1);
names.add(this.username);
Message message = new Message();
message.setAlert(this.username + "进入聊天室!!");
message.setNames(names);
broadcast(sockets, gson.toJson(message));
}
//退出
@OnClose
public void close(Session session) {
sockets.remove(this);
names.remove(this.username);
Message message = new Message();
message.setAlert(this.username + "退出聊天室!!");
message.setNames(names);
broadcast(sockets, gson.toJson(message));
}
//发送
@OnMessage
public void receive(Session session,String msg ){
Message message=new Message();
message.setSendMsg(msg);
message.setFrom(this.username);
message.setDate(new Date().toLocaleString());
broadcast(sockets, gson.toJson(message));
}
public void broadcast(Set<ChatSocket> ss, String msg) {
for (Iterator iterator = ss.iterator(); iterator.hasNext();) {
ChatSocket chatSocket = (ChatSocket) iterator.next();
try {
chatSocket.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
chat.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
var ws;
var username = getUrlParameter('username');
var url = "ws://localhost:8080/websocket/chatSocket?username="
+ username;
window.onload = connect;
function connect() {
if ('WebSocket' in window) {
ws = new WebSocket(url);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(url);
} else {
alert('该浏览器不支持websocket');
return;
}
ws.onmessage = function(event) {
eval("var result=" + event.data);
//欢迎语言
if (result.alert != undefined) {
document.getElementById("content").innerHTML += result.alert
+ "<br/>";
}
//列表
if (result.names != undefined) {
document.getElementById("userList").innerHTML = "";
var arr = result.names;
for (var i = 0; i < arr.length; i++) {
document.getElementById("userList").innerHTML += arr[i]
+ "<br/>";
}
}
//聊天内容
if (result.from != undefined) {
document.getElementById("content").innerHTML += result.from
+ " " + result.date + " 说:<br/>" + result.sendMsg
+ "<br/>";
}
};
}
function wsSend() {
var msg = document.getElementById("msg");
ws.send(msg.value);
msg.value = "";
}
//截取URL 中的传过来的值
function getUrlParameter(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.parent.location.href);
if (results == null)
return "";
else {
return results[1];
}
}
</script>
</head>
<body>
<div id="content"
style="border: 1px solid black; width: 400px; height: 300px; float: left;"></div>
<div id="userList"
style="border: 1px solid black; width: 100px; height: 300px; float: left;"></div>
<div style="clear: both;">
<input id="msg" />
<button onclick="wsSend()">send</button>
</div>
</body>
</html>