irpas技术客

WebSocket聊天小例子(附源码)_学习日记_websocket在线聊天源码

大大的周 2825

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(); // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。 private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>(); // 发送消息 public void sendMessage(Session session, String message) throws IOException { if (session != null) { synchronized (session) { // System.out.println("发送数据:" + message); 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); // session.getBasicRemote().sendText("你好,我是服务端"); JSONObject jsonObject = (JSONObject) JSON.parse(message); System.out.println(jsonObject); // sendMessage(sessionPools.get(jsonObject.get("tsid")), String.valueOf(jsonObject.get("sid"))+"--给你发来消息:"+String.valueOf(jsonObject.get("txt"))); // System.out.println( String.valueOf(jsonObject.get("sid"))+"发送消息成功"); 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~


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #websocket在线聊天源码