WebSocket聊天小例子(附源码)
还记得之前我们用c#写过一个聊天室,但是是cs的,我们都知道现在流行的是bs架构,所以很相似C#用的是socket底层是tcp和udp而websocket其实就是在http的基础上模仿tcp和udp握手和挥手
基于C#的socket聊天室(附源码): https://blog.csdn.net/hello_list/article/details/124075029
原理嘛都差不多,要我说一个文章讲原理不如直接上例子上代码的方便,讲解一下这个小例子就懂了;
这里呢我们使用的是tomcat自带的依赖,所以不用导入,还有一种方法是spring的,这里就不说了;
体验
我们先尝试体验下效果
将Web项目运行起来,一个特别简单的页面,其实页面我们可以去扒就可以,比如csdn的私信页面,拿去用就行,功能还那么个功能,但是我这里主要是功能,就没有扒页面,看完这个例子,完全可以去做一个csdn这样的私信功能;
先看下我这个简陋的页面
我们再看下功能,可简单了,会用吧
输入id点击获取连接;连接成功之后,这个时候id就固定了,我这里直接锁住了
我们再开两个,三个用户我们就连接成功了;
这里也可以看下后端日志
我们可以给在线的用户发送消息,只需要输入对方id,我这里就试着互相发了几条消息:
功能到这里就结束了,我们看下是怎么实现的,简单理解下,可简单了;
服务端
服务端代码,一个java文件就搞定
package servlet;
import java.io.IOException;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@ServerEndpoint("/webSocket/{sid}")
public class TestWebSocket {
private static AtomicInteger onlineNum = new AtomicInteger();
private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
public void sendMessage(Session session, String message) throws IOException {
if (session != null) {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
}
}
@OnOpen
public void onOpen(Session session, @PathParam(value = "sid") String sid) throws IOException {
System.out.println("新连接");
sessionPools.put(sid, session);
addOnlineCount();
System.out.println(sid + "加入webSocket!当前人数为" + onlineNum);
sendMessage(session, "欢迎" + sid + "加入连接!");
}
@OnClose
public void onClose() {
subOnlineCount();
System.out.println("连接关闭");
}
@OnMessage
public void onMessage(String message, Session session) throws IOException {
System.out.println("收到消息");
System.out.println(message);
JSONObject jsonObject = (JSONObject) JSON.parse(message);
System.out.println(jsonObject);
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("fromid", String.valueOf(jsonObject.get("sid")));
jsonObject2.put("text", String.valueOf(jsonObject.get("txt")));
sendMessage(sessionPools.get(jsonObject.get("tsid")), jsonObject2.toJSONString());
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
public static void addOnlineCount() {
onlineNum.incrementAndGet();
}
public static void subOnlineCount() {
onlineNum.decrementAndGet();
}
}
客户端,其实就是网页端
所以说前后就两个文件,这里我们在客户端创建一个websocket然后去连接服务端即可;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="sid">
<button οnclick="lianjie()">请输入id然后点击连接</button>
<hr>
<br> 消息输入:
<input type="text" id="txt" />
<br> 消息接收人的id:
<input type="text" id="tsid" />
<button οnclick="cli()">点击发送</button>
<br>
<hr>
以下是消息区域:
<div id="app"></div>
<script>
var websocket = null;
function lianjie() {
//判断当前浏览器是否支持websocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8081/web/webSocket/"+document.getElementById("sid").value);
} else {
alert('当前浏览器 not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
alert("连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function () {
//websocket.send("hello")
alert("连接成功");
var sid = document.getElementById("sid")
sid.readOnly = true
sid.style.backgroundColor='#ddd'
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
//console.log("收到服务端消息"+event.data)
console.log(event.data)
var json = JSON.parse(event.data)
innerdiv(json.fromid,json.text)
}
//连接关闭的回调方法
websocket.onclose = function () {
setmessageinnerhtml("websocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closewebsocket();
}
}
//发送消息
function cli() {
var sid = document.getElementById("sid") //发送者id
var txt = document.getElementById("txt").value //发送消息
var tsid = document.getElementById("tsid").value //接收者id
var m = new Map(); // 空Map
m.set("sid",sid.value);
m.set("txt",txt)
m.set("tsid",tsid)
json = mapToJson(m)
console.log(json)
websocket.send(json)
innerdiv("我",txt)
}
//关闭websocket连接
function closewebsocket() {
websocket.close();
}
function strMapToObj(strMap){
var obj= Object.create(null);
for (var[k,v] of strMap) {
obj[k] = v;
}
return obj;
}
/**
*map转换为json
*/
function mapToJson(map) {
return JSON.stringify(strMapToObj(map));
}
/*
添加聊天记录
*/
function innerdiv(id,txt){
var app = document.getElementById("app")
app.innerHTML += "<div>"+ id +": "+txt+ "</div>"
}
</script>
</body>
</html>
小结
看到这里的同学都知道,博主就喜欢给大家留出优化空间,比如根据这个实现下csdn的私信功能,把页面拔下来都是现成的,对吧,所以都看到这里了,还不留个关注,点个赞吗,bye~
|