环境
java:1.7
websocket:1.3.0(Java-WebSocket-1.3.0.jar)
前言
因为想了解消息推送
,而研究kafka
,在研究时,自己感觉,要是我自己写一个类似的是不是更容易理解这些框架技术,想想单单实现消息推送
这还是可行的,接着就想到了今天要讲的websocket
。
在网上搜索了很多教程,包括外文,都是基于容器的,比如:tomcat
、jetty
等等。
因为我之前研究过密钥交换
,所以我坚信,即使不使用容器
也可以实现消息推送
的。
服务器端代码
通过继承WebSocketServer
,并且显示指定两个构造函数,其中一个参数是端口号:
package websocketJava.simple;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Set;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
public class ChatServer extends WebSocketServer{
public ChatServer(int port) throws UnknownHostException{
super(new InetSocketAddress(InetAddress.getLocalHost(), port));
}
public ChatServer(InetSocketAddress address) {
super(address);
}
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
sendToAll("new");
System.out.println(webSocket + "entered the room!");
}
@Override
public void onClose(WebSocket webSocket, int n, String str, boolean bool) {
sendToAll(webSocket + "has left the room!");
System.out.println( webSocket + " has left the room!" );
}
@Override
public void onMessage(WebSocket webSocket, String message) {
sendToAll(message);
System.out.println("========="+message+"=========");
System.out.println( webSocket + ": " + message );
}
@Override
public void onError(WebSocket webSocket, Exception e) {
e.printStackTrace();
}
public void sendToAll(String text){
Set<WebSocket> con = (Set<WebSocket>) connections();
synchronized (con) {
for(WebSocket c : con){
c.send(text);
}
}
}
}
接着我们再写启动主方法:
package websocketJava.simple;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Smain {
public static void main(String[] args) throws Exception {
int port = 8887;
ChatServer s = new ChatServer(port);
s.start();
System.out.println("ChatServer started on port " + s.getPort());
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
// s.run();
while(true){
String in = sysin.readLine();
s.sendToAll(in);
}
}
}
前端代码
前端代码用的是HTML/js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>消息推送</title>
</head>
<body>
Welcome<br/>
<input id="text" type="text"/>
<button onclick="send()">发送消息</button>
<hr/>
<button onclick="closeWebSocket()">关闭WebSocket连接</button>
<hr/>
<div id="message"></div>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
// websocket = new WebSocket("ws://192.168.152.85:8098");
// websocket = new WebSocket("ws://ggmes.push.sandbox.gofund.cn:8093");
websocket = new WebSocket("ws://192.168.152.85:8887");
websocket.extensions = "asdfds";
console.log(websocket);
}
else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function () {
setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
}
//连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</body>
</html>
说明:
请求地址另一种写法:
var wsUri = getRootUri() + "/websocket/demo";
function getRootUri() {
return "ws://" + (document.location.hostname == "" ? "192.168.152.85" : document.location.hostname) + ":" +
(document.location.port == "" ? "8080" : document.location.port);
}
假设当前页面请求端口号就是websocket的端口号,就这可以使用这个方法
启动main方法后
测试结果如下:
控制台
前端
总结
我之后又尝试使用注解(Annotation)的方法来做,我没有成功;
因为写到一半时,发现:
①使用注解@ServerEndpoint
,不知道怎么指定端口;
②假设就使用默认80
端口,接下来我又不知道如何启动它。
主要是第二点:因为使用继承WebSocketServer
类时,可以使用封装的start
或者run
方法来启动,这些都是现成的。而注解假设不使用容器(tomcat
、jetty
)的话,实在是不知道怎么启动服务端(查了很久的资料)。
为什么我这么执迷不使用容器来启动呢?
我也不知道,总感觉最原始的,才是最好理解的!
参考地址: