WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。
反向Ajax在观察者模型、聊天系统中应用的越来越多。如股票,监控等系统。
以聊天系统为例,如果没有服务器推的技术,Web聊天系统只能以固定的时间间隔轮询服务器。
这会产生大量的无用的连接,对服务器造成巨大压力。
在单位写过一个IM聊天系统,在配置了线程池,内存缓存等优化手段之后,通过loadrunner压力测试,并发访问量却始终超不过200/s。在这种系统中,轮询是一种噩梦。
WebSocket作为服务器推(反向Ajax)的手段之一,可以解决这种需求。
下面的例子,简单介绍了WebSocket的使用。
服务器每隔3秒,将自身的内存信息推送到所有连接的客户端浏览器。如果客户端浏览器点击按钮,则立即对该客户端返回最新的信息。
页面:
但是在Tomcat 7.0.47版本中,WebSocketServlet已经标识为deprecated,并可能在Tomcat 8中remove。
是不是设计了更好的API
反向Ajax在观察者模型、聊天系统中应用的越来越多。如股票,监控等系统。
以聊天系统为例,如果没有服务器推的技术,Web聊天系统只能以固定的时间间隔轮询服务器。
这会产生大量的无用的连接,对服务器造成巨大压力。
在单位写过一个IM聊天系统,在配置了线程池,内存缓存等优化手段之后,通过loadrunner压力测试,并发访问量却始终超不过200/s。在这种系统中,轮询是一种噩梦。
WebSocket作为服务器推(反向Ajax)的手段之一,可以解决这种需求。
下面的例子,简单介绍了WebSocket的使用。
服务器每隔3秒,将自身的内存信息推送到所有连接的客户端浏览器。如果客户端浏览器点击按钮,则立即对该客户端返回最新的信息。
页面:
<!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>WebSocket</title>
<script type="text/javascript"
src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript">
var ws = null;
function startWebSocket() {
if ('WebSocket' in window) {
ws = new WebSocket('ws://127.0.0.1:8080/Web/ws.do');
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket('ws://127.0.0.1:8080/Web/ws.do');
} else {
alert('浏览器不支持WebSocket');
}
ws.onmessage = function(evt) {
$('#content').html(evt.data);
}
ws.onclose = function(evt) {
$('#content').html('WebSocket关闭');
}
ws.onopen = function(evt) {
$('#content').html('WebSocket已经打开');
}
}
function getJVMInfo() {
//随便发点什么
ws.send(new Date());
}
$(document).ready(function() {
startWebSocket();
});
</script>
</head>
<body>
<input type="button" value="立即获取" onclick="getJVMInfo();" />
<div id="content"></div>
</body>
</html>
代码:<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WebSocket</title>
<script type="text/javascript"
src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript">
var ws = null;
function startWebSocket() {
if ('WebSocket' in window) {
ws = new WebSocket('ws://127.0.0.1:8080/Web/ws.do');
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket('ws://127.0.0.1:8080/Web/ws.do');
} else {
alert('浏览器不支持WebSocket');
}
ws.onmessage = function(evt) {
$('#content').html(evt.data);
}
ws.onclose = function(evt) {
$('#content').html('WebSocket关闭');
}
ws.onopen = function(evt) {
$('#content').html('WebSocket已经打开');
}
}
function getJVMInfo() {
//随便发点什么
ws.send(new Date());
}
$(document).ready(function() {
startWebSocket();
});
</script>
</head>
<body>
<input type="button" value="立即获取" onclick="getJVMInfo();" />
<div id="content"></div>
</body>
</html>
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
/**
* Servlet implementation class InitServlet
*/
@WebServlet("/ws.do")
public class InitServlet extends WebSocketServlet implements Runnable {
List<JVMMessageInbound> list = new CopyOnWriteArrayList<JVMMessageInbound>();
ScheduledExecutorService singleThread = Executors.newSingleThreadScheduledExecutor();
{
singleThread.scheduleWithFixedDelay(this, 3, 3, TimeUnit.SECONDS);
}
@Override
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest arg1) {
return new JVMMessageInbound();
}
private class JVMMessageInbound extends MessageInbound {
@Override
protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
}
@Override
protected void onTextMessage(CharBuffer arg0) throws IOException {
CharBuffer cb = CharBuffer.wrap(arg0);
String data = cb.toString();
System.out.println(data);
this.getWsOutbound().writeTextMessage(CharBuffer.wrap(getJVMInfo()));
this.getWsOutbound().flush();
}
@Override
protected void onClose(int status) {
System.out.println("Close WebSocket");
super.onClose(status);
list.remove(this);
}
@Override
protected void onOpen(WsOutbound outbound) {
System.out.println("Open new WebSocket");
super.onOpen(outbound);
list.add(this);
}
}
private String getJVMInfo() {
long useMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
useMemory = useMemory / 1024;
return "已用内存:" + String.valueOf(useMemory) + "K";
}
@Override
public void run() {
System.out.println("发送广播通知");
String data = "广播通知\n" + new Date() + "\n" + getJVMInfo();
for (JVMMessageInbound m : list) {
try {
m.getWsOutbound().writeTextMessage(CharBuffer.wrap(data));
m.getWsOutbound().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
效果截图:import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
/**
* Servlet implementation class InitServlet
*/
@WebServlet("/ws.do")
public class InitServlet extends WebSocketServlet implements Runnable {
List<JVMMessageInbound> list = new CopyOnWriteArrayList<JVMMessageInbound>();
ScheduledExecutorService singleThread = Executors.newSingleThreadScheduledExecutor();
{
singleThread.scheduleWithFixedDelay(this, 3, 3, TimeUnit.SECONDS);
}
@Override
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest arg1) {
return new JVMMessageInbound();
}
private class JVMMessageInbound extends MessageInbound {
@Override
protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
}
@Override
protected void onTextMessage(CharBuffer arg0) throws IOException {
CharBuffer cb = CharBuffer.wrap(arg0);
String data = cb.toString();
System.out.println(data);
this.getWsOutbound().writeTextMessage(CharBuffer.wrap(getJVMInfo()));
this.getWsOutbound().flush();
}
@Override
protected void onClose(int status) {
System.out.println("Close WebSocket");
super.onClose(status);
list.remove(this);
}
@Override
protected void onOpen(WsOutbound outbound) {
System.out.println("Open new WebSocket");
super.onOpen(outbound);
list.add(this);
}
}
private String getJVMInfo() {
long useMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
useMemory = useMemory / 1024;
return "已用内存:" + String.valueOf(useMemory) + "K";
}
@Override
public void run() {
System.out.println("发送广播通知");
String data = "广播通知\n" + new Date() + "\n" + getJVMInfo();
for (JVMMessageInbound m : list) {
try {
m.getWsOutbound().writeTextMessage(CharBuffer.wrap(data));
m.getWsOutbound().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
但是在Tomcat 7.0.47版本中,WebSocketServlet已经标识为deprecated,并可能在Tomcat 8中remove。
是不是设计了更好的API
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29254281/viewspace-1064838/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/29254281/viewspace-1064838/