前言
使用Java WebSocket包实现聊天窗口,最朴素的实现,大道至简
WebSocket基础
所用jar包,Java-WebSocket依赖了日志包
Java-WebSocket-1.5.2.jar
slf4j-log4j12-1.7.32.jar
slf4j-api-1.7.32.jar
slf4j-api-1.7.32.jar
一、WebSocketServer类
建立WebSocketServer类作为服务端
on开头的方法监听对应状态,webSocket.send()向客户端发送数据
public class WsServer extends WebSocketServer {
static {
//使用默认log配置,不是因为懒,大道至简
BasicConfigurator.configure();
}
private static Logger log = Logger.getLogger(WsServer.class);
private static int userid = 1;
/**保存用户连接和用户id*/
public static final HashMap<WebSocket, Integer> users = new HashMap<>();
public WsServer(int port) {
super(new InetSocketAddress(port));
}
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
System.out.println(clientHandshake.getResourceDescriptor());
log.info("--------------------onOpen--------------------");
System.out.println(webSocket.getRemoteSocketAddress()+"已连接");
webSocket.send("服务器:hello,用户"+userid+"你已成功连接");
String str = "用户"+userid+"加入聊天";
users.put(webSocket, userid);
broadcastMsg(webSocket,str);
userid++;
}
@Override
public void onClose(WebSocket webSocket, int i, String s, boolean b) {
log.info("--------------------onClose--------------------");
users.remove(webSocket);
String str = "用户"+users.get(webSocket)+"退出聊天";
broadcastMsg(webSocket,str);
}
@Override
public void onMessage(WebSocket webSocket, String s) {
log.info("--------------------onMessage--------------------");
System.out.println("收到" + webSocket.getRemoteSocketAddress() + "的消息:" + s);
//webSocket.send("回复" + webSocket.getRemoteSocketAddress());
broadcastMsg(webSocket,s);
}
@Override
public void onError(WebSocket webSocket, Exception e) {
log.info("--------------------onError--------------------");
webSocket.send("出错了...");
}
@Override
public void onStart() {
log.info("--------------------Server onStart--------------------");
}
public void broadcastMsg(WebSocket webSocket, String s){
for (Map.Entry<WebSocket, Integer> user:
users.entrySet()) {
user.getKey().send("用户"+users.get(webSocket)+":"+s);
}
}
}
二、启动类
WebSocketServer实现Runnable直接启动即可
public class Main {
public static void main(String[] args) {
WsServer wsServer = new WsServer(8888);
wsServer.start();
}
}
三、前端页面
注意实现ws.close()的function的名字不能是close,会没有反应
没加css效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket 客户端</title>
</head>
<body>
<div id="sse">
<input id="WebSocketServer" value="ws://localhost:8888">
<button onclick="getConnection()">连接WebSocket</button>
<button onclick="closeConnection()">关闭WebSocket</button>
</br>
<input id="message" value="一条消息">
<button onclick="sendMessage()">发送</button>
</br>
<div id="messageBox">
<div><span>welcome!</span></div>
</div>
</div>
</body>
<script type="text/javascript">
let ws = null;
let messageBox = document.getElementById("messageBox");
function getConnection() {
if (!"WebSocket" in window) {
alert("您的浏览器不支持 WebSocket!");
}
ws = new WebSocket(document.getElementById("WebSocketServer").value);
ws.onmessage = function (evt) {
//alert("数据接收" + evt.data);
let str = '<div><span>' + evt.data + '</span></div>';
messageBox.innerHTML = messageBox.innerHTML + str;
};
ws.onerror = function () {
alert("出错了...")
}
ws.onclose = function () {
// 关闭 websocket
alert("连接已关闭...");
};
}
function sendMessage() {
if (ws == null || ws.readyState === 3) {
alert("请先连接到websocketServer");
return;
}
//console.log(ws.readyState)
ws.send(document.getElementById("message").value)
document.getElementById("message").value = '';
}
//注意:fun名不能是close,会没反应
function closeConnection() {
ws.close(1000);
}
</script>
</html>
四、效果图
页面1
页面2
五、其他
流程:server初始化-client发送请求-onopen建立连接-msg/error-close
这个WebSocketSelector和WebSocketWorker应该类似nio,WebSocketSelector监听并且选择对应WebSocketWorker