分享基于 websocket 网页端聊天室
博客地址:https://ainyi.com/67
有一个月没有写博客了,也是因为年前需求多、回家过春节的原因,现在返回北京的第二天,想想,应该也要分享技术专题的博客了!!
主题
基于 websocket 网页端聊天室
WebSocket 协议是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工 (full-duplex) 通信——允许服务器主动发送信息给客户端。
使用 java 开发后台
需要导入一个jar包:javax.websocket-api-1.0-rc4.jar
后台代码
package com.krry.socket;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
@ServerEndpoint("/websocket")
public class MyWebSocket {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
//群发消息
for(MyWebSocket item: webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
MyWebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
MyWebSocket.onlineCount--;
}
}
前端代码
注意
前端需要实现这几个方法:
// 注册事件
// 监听打开连接
ws.onopen = function(){
openWs();
};
// 监听消息
ws.onmessage = function(event){
msgWs(event);
};
// 监听关闭连接
ws.onclose = function(){
closeWs();
};
// 监听发送错误
ws.onerror = function(){
errorWs();
};
具体代码
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta name="keywords" content="">
<meta name="description" content="">
<title>
基于Java服务器端的消息主动推送技术揭秘 --krry
</title>
<link rel="stylesheet" href="css/animate.css" />
<link rel="stylesheet" type="text/css" href="css/sg.css" />
<style>
*{margin:0;padding:0;} body{background:url("images/5.jpg");background-size:cover;}
h1{margin-top:50px;text-align:center;color:#fff;text-shadow:1px 1px 1px
#000;font-family:-webkit-body;font-size:24px;} .box{width:700px;margin:20px
auto;} .box span{color:#f60;font-size:16px;font-family:"微软雅黑";} .box .shu{text-indent:1em;height:24px;font-family:"微软雅黑";border:0;outline:none;font-size:14px;}
.box .add{width:300px;margin-right:24px;} .box .user{width:200px;} .box
.btn{width:80px;height:34px;color:#fff;background:#6c0;border:0;outline:none;cursor:pointer;margin-top:20px;font-size:16px;font-family:"微软雅黑";}
.box .area{line-height: 29px;height:280px;width:680px;padding:10px;overflow:auto;font-size:16px;font-family:"微软雅黑";margin:20px
0;outline:none;box-shadow:1px 2px 18px #000} .box .setex{text-indent:1em;height:28px;border:1px
solid #6c0;width:618px;outline:none;float:left;font-family:"微软雅黑";} .box
.send{font-size:14px;width:80px;height:30px;color:#fff;background:#6c0;border:0;outline:none;cursor:pointer;font-family:"微软雅黑";}
</style>
</head>
<body>
<h1>
基于Java服务器端的消息主动推送技术揭秘 --krry
</h1>
<div class="box">
<span>
服务器地址:
</span>
<input type="text" class="shu add" value="www.ainyi.com/krry_NetChat/websocket"
readonly/>
<span>
用户名:
</span>
<input type="text" class="shu user" value="匿名" />
<input type="button" value="连接" class="btn" />
<div class="area" id="boxx">
</div>
<div class="c_cen">
<input type="text" class="setex" />
<input type="button" value="发送" class="send">
</div>
</div>
<script src="js/jquery-1.11.1.min.js">
</script>
<script src="js/sg.js">
</script>
<script src="js/sgutil.js">
</script>
<script>
var close = true;
var ws;
$(function() {
$(".c_cen").hide();
//首先判断浏览器是否支持webSocket,支持h5的浏览器才会支持
if (window.WebSocket) {
printMsg("您的浏览器支持WebSocket,您可以尝试连接到聊天服务器!", "OK");
} else {
printMsg("您的浏览器不支持WebSocket,请选择其他浏览器!", "ERROR");
//设置按钮不可点击
$(".btn").attr("disabled", "true");
}
});
//打印信息
function printMsg(msg, msgType) {
if (msgType == "OK") {
msg = "<span style='color:green'>" + msg + "</span>";
}
if (msgType == "ERROR") {
msg = "<span style='color:red'>" + msg + "</span>";
}
$(".area").append(msg + "<br/>");
var boxx = document.getElementById("boxx");
boxx.scrollTop = boxx.scrollHeight; //使滚动条一直在底部
}
//打开Socket
function openWs() {
printMsg("链接已建立", "OK");
ws.send("【" + $(".user").val() + "】已进入聊天室");
$(".c_cen").show();
}
//接收消息的时候
function msgWs(e) {
printMsg(e.data);
}
//关闭连接
function closeWs() {
$(".btn").val("连接");
$(".c_cen").hide();
}
//产生错误
function errorWs() {
printMsg("您与服务器连接错误...", "ERROR");
}
//点击发送按钮
$(".send").click(function() {
var text = $(".setex").val();
if (text == null || text == "") return;
$(".setex").val("");
ws.send("【" + $(".user").val() + "】:" + text);
});
//点击连接
$(".btn").click(function() {
if ($(".add").val() && $(".user").val()) {
if (close) {
printMsg("正在准备连接服务器,请稍等...");
var url = "wss://" + $(".add").val();
if ("WebSocket" in window) {
ws = new WebSocket(url);
} else if ("MozWebSocket" in window) {
ws = new MozWebSocket(url);
}
//已连接
$(".btn").val("断开");
close = false;
//注册事件
ws.onopen = function() {
openWs();
};
ws.onmessage = function(event) {
msgWs(event);
};
ws.onclose = function() {
closeWs();
};
ws.onerror = function() {
errorWs();
};
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
ws.send("【" + $(".user").val() + "】离开了聊天室");
close = true;
ws.close();
};
} else {
ws.send("【" + $(".user").val() + "】离开了聊天室");
close = true;
ws.close();
}
} else {
$.tmDialog.alert({
open: "left",
content: "服务器地址和用户名不能为空哦...",
title: "提示哦~~~"
});
}
});
//回车键
$(".setex").keypress(function(event) {
if (event.keyCode == 13) {
$(".send").trigger("click");
}
});
</script>
</body>
</html>
到这里大功告成
聊天方法
- 打开两个窗口输入项目地址进行聊天
- 可以把链接发给朋友打开,进行聊天
来一波截图
移动端
在线演示
PC 端:https://www.ainyi.com/krry_NetChat
移动端:https://www.ainyi.com/krry_NetChatPho
打完收工~
博客地址:https://ainyi.com/67
分享基于 websocket 网页端聊天室的更多相关文章
- java 开发 websocket 网页端聊天室
博客地址:https://ainyi.com/67 WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端. ...
- workerman-chat(PHP开发的基于Websocket协议的聊天室框架)(thinkphp也是支持socket聊天的)
workerman-chat(PHP开发的基于Websocket协议的聊天室框架)(thinkphp也是支持socket聊天的) 一.总结 1.下面链接里面还有一个来聊的php聊天室源码可以学习 2. ...
- .NET Core 基于Websocket的在线聊天室
什么是Websocket 我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后 ...
- Netty 系列八(基于 WebSocket 的简单聊天室).
一.前言 之前写过一篇 Spring 集成 WebSocket 协议的文章 —— Spring消息之WebSocket ,所以对于 WebSocket 协议的介绍就不多说了,可以参考这篇文章.这里只做 ...
- Flask基于websocket的简单聊天室
1.安装gevent-websocket pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ gevent-websocket 2.cha ...
- 基于WebSocket的简易聊天室
用的是Flash + WebSocket 哦~ Flask 之 WebSocket 一.项目结构: 二.导入模块 pip3 install gevent-websocket 三.先来看一个一对一聊天的 ...
- 如何利用WebSocket实现网页版聊天室
花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...
- 基于Node.js + WebSocket 的简易聊天室
代码地址如下:http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.js ...
- vue仿微信网页版|vue+web端聊天室|仿微信客户端vue版
一.项目介绍 基于Vue2.5.6+Vuex+vue-cli+vue-router+vue-gemini-scrollbar+swiper+elementUI等技术混合架构开发的仿微信web端聊天室— ...
随机推荐
- jenkins+docker 持续构建非docker in docker
工欲善其事必先利其器,为了解脱程序员的,我们程序员本身发明了很多好用的工具,通过各种工具的组合来达到我们想要的结果 本文采用jenkins docker svn maven作为相关工具,项目sprin ...
- CTF中常见的加解密(经典)
今天一早起来,就要去做早操,心里苦呀! 但是不影响我为未来的学弟学妹整理资料的心情呀!希望我的一些拙见能够帮助到学弟学妹! 永远爱你们的 ---- 新宝宝 ASCII编码 ASCII 码使用指定的7 ...
- GIL(全局解释器锁)
GIL(全局解释器锁) 每个线程在执行的过程都需要先获取GIL 作用:在单核的情况下实现多任务(多线程),保证同一时刻只有一个线程可以执行代码,因此造成了我们使用多线程的时候无法实现并 ...
- 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(二)
前一节已经完成了Oracle数据库和ODI的安装,并已经为ODI在Oracle数据库中创建了两个用户,分别用于存放主资料库数据和工作资料库数据,在ODI中完成主资料库和工作资料库的创建,也分别为其创建 ...
- go语言调度器源代码情景分析之五:汇编指令
本文是<go调度器源代码情景分析>系列 第一章 预备知识的第4小节. 汇编语言是每位后端程序员都应该掌握的一门语言,因为学会了汇编语言,不管是对我们调试程序还是研究与理解计算机底层的一些运 ...
- 如何使用FluentMigrator进行数据库迁移
标题:如何使用FluentMigrator进行数据库迁移 地址:https://www.cnblogs.com/lwqlun/p/10649949.html 作者: Lamond Lu FluentM ...
- Git协同工作流介绍
git相关的文章和教程非常多,但是系统介绍和了解工作流的人并不多,在使用过程中用错或用偏的也不少,这里分享的是,假设你已经入门的情况下,我们如何去选择适合团队需要的工作流. git优势 这里先唠叨gi ...
- Java对字符串加密并返回星号※
If you don't look back, you'll never know I waiting for you behind you. Java对字符串加密并返回星号※ PasswordUt ...
- vue表格实现固定表头首列
前言 最近在做vue移动端项目,需要做一个可以固定表头首列的表格,而且由于一些原因不能使用任何UI插件,网上找了很久也没什么好方法,所以在解决了问题之后,写下了这篇文章供后来人参考,文章有什么错漏的问 ...
- HTML文档编写规范
(1)HTML标记是由尖括号包围的关键词.所有标记均以“<”开始,以“>”结束.结束的标记在开始名称前加上斜杠“/”.例如头部标记格式如下所示:<head> ……</he ...