标签:
这几天想做一个单对单的在线聊天模块,所以研究了一下websocket,以下就来分享一下基于tomcat7的websocket实现的小例子。
1.WebSocket是什么
WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。
它摒弃了以轮询为主要方式的传统的即时通讯技术,真正实现了一个浏览器与服务器之间的全双工通讯,通过一个握手的动作,使得浏览器与服务器之间形成一条通道,实现数据的互相传送。
1 import java.util.Set; 2 import java.util.concurrent.CopyOnWriteArraySet; 3 4 import javax.servlet.http.HttpServletRequest; 5 6 import org.apache.catalina.websocket.StreamInbound; 7 import org.apache.catalina.websocket.WebSocketServlet; 8 9 10 public class WebSocketServer extends WebSocketServlet { 11 12 public final Set<ChatWebSocket> users = new CopyOnWriteArraySet<ChatWebSocket>(); 13 14 @Override 15 protected StreamInbound createWebSocketInbound(String arg0, 16 HttpServletRequest arg1) { 17 // TODO Auto-generated method stub 18 return new ChatWebSocket(users); 19 } 21 }
浏览器的每一次连接都会经过WebSocketServer 的createWebSocketInbound方法,这里返回一个ChatWebSocket实例(文章接下来会实现),这里还维护了一个每一个连接对象users。
关于CopyOnWriteArraySet可以看这里http://ifeve.com/tag/copyonwritearrayset/
3)ChatWebSocket.java
1 import java.io.IOException; 2 import java.nio.ByteBuffer; 3 import java.nio.CharBuffer; 4 import java.util.Set; 5 import java.util.concurrent.CopyOnWriteArraySet; 6 7 import org.apache.catalina.websocket.MessageInbound; 8 import org.apache.catalina.websocket.WsOutbound; 9 10 public class ChatWebSocket extends MessageInbound { 11 12 public Set<ChatWebSocket> users = new CopyOnWriteArraySet<ChatWebSocket>(); 13 private String username; 14 15 public ChatWebSocket() { 16 } 17 18 public ChatWebSocket(Set<ChatWebSocket> users) { 19 this.users = users; 20 } 21 22 /** 23 * 此方法会接收浏览器的二进制消息 24 */ 25 @Override 26 protected void onBinaryMessage(ByteBuffer message) throws IOException { 27 // TODO Auto-generated method stub 28 System.out.println("binary:"+message); 29 } 30 31 /** 32 * 此方法接收浏览器的文本消息,以下的for循环是用来查找名字实现单对单聊天用的 33 */ 34 @Override 35 protected void onTextMessage(CharBuffer message) throws IOException { 36 // TODO Auto-generated method stub 37 System.out.println("text:"+message); 38 String mes = String.valueOf(message); 39 if(mes.indexOf("username:")==0) { 40 this.username = mes.substring(9); 41 System.out.println(username); 42 } else { 43 String[] str = mes.split("_123"); 44 String name = str[0]; 45 for(ChatWebSocket user :users) { 46 if(user.username.equals(name)) { 47 CharBuffer ch = CharBuffer.wrap(this.username+":123"+str[1]); 48 System.out.println("find"); 49 user.getWsOutbound().writeTextMessage(ch); 50 break; 51 } 52 } 53 } 54 55 } 56 57 /** 58 * 关闭连接会经过此方法 59 */ 60 @Override 61 protected void onClose(int status) { 62 // TODO Auto-generated method stub 63 System.out.println("----"); 64 System.out.println("close"); 65 users.remove(this); 66 } 67 68 /** 69 * 浏览器连接会经过此方法 70 */ 71 @Override 72 protected void onOpen(WsOutbound outbound) { 73 // TODO Auto-generated method stub 74 75 System.out.println("open"); 76 users.add(this); 77 } 78 79 public String getUsername() { 80 return username; 81 } 82 83 public void setUsername(String username) { 84 this.username = username; 85 } 89 }
4) 当然还要在web.xml上配置这个servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>websocketserver</servlet-name>
<servlet-class>WebSocketServer1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>websocketserver</servlet-name>
<url-pattern>/webchat</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
至此,服务器端已搭建结束。
<%@ 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">
<script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="js/socket.js"></script>
<title>webClient</title>
</head>
<body>
<table id="mes">
<tr>
<td>名字</td>
<td><input type="text" id="othername"></td>
</tr>
<tr>
<td>消息</td>
<td><input type="text" id="message"></td>
</tr>
<tr>
<td><input id="sendbutton" type="button" value="send" onClick="click" disabled="true">
</input></td>
</tr>
</table>
<div id="record">
</div>
</body>
</html>
以下是页面引入的soket.js
var username = window.prompt("输入你的名字:");
document.write("Welcome<p id=\"username\">" + username + "</p>");
/**
* 判断浏览器是否支持websocket
*/
if (!window.WebSocket && window.MozWebSocket)
window.WebSocket = window.MozWebSocket;
if (!window.WebSocket)
alert("No Support ");
var ws;
$(document).ready(function() {
$("#sendbutton").click(sendMessage);
startWebSocket();
});
function sendMessage() {
var othername = $("#othername").val();
var msg = othername + "_123" + $("#message").val();
send(msg);
};
function send(data) {
//alert(data);
ws.send(data);
};
function startWebSocket() {
ws = new WebSocket("ws://localhost:8080/websocketDemo/webchat");
//浏览器连接会自动执行这个open方法
ws.onopen = function() {
console.log("success open");
send("username:"+username);
};
//服务端向浏览器发送消息会经过此方法
ws.onmessage = function(event) {
console.log("RECEIVE:" + event.data);
handleData(event.data);
};
//浏览器关闭连接会经过此方法
ws.onclose = function(event) {
console.log("Client notified socket has closed", event);
};
};
function handleData(data) {
var vals = data.split(":123");
var name = vals[0];
var mess = vals[1];
$("#record").append("<p>" + name+":" +mess+ "</p>");
}
3.后记
在tomcat8以后,已经出现了新的支持websocket的方式了,可以直接用注解的方式去代替本例子中的继承,注解的方式为@ServerEndpoint(value="/") ,@OnOpen,@OnMessage,@OnClose等等
由于我的eclipse版本没支持tomcat8,所以本文章就只写了基于tomcat7的实现。理解了本例子,相信用注解的方式也是很容易的了。
标签:
原文地址:http://www.cnblogs.com/detoAndy/p/5079788.html