博客地址:https://ainyi.com/67

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

需要导入一个jar包:javax.websocket-api-1.0-rc4.jar

注意点:

需要实现这几个方法:

 //注册事件
ws.onopen = function(){
openWs();
};
ws.onmessage = function(event){
msgWs(event);
};
ws.onclose = function(){
closeWs();
};
ws.onerror = function(){
errorWs();
};

后台代码:

 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--;
}
}

前端代码:

 <%@ 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="localhost/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 = "ws://"+$(".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>

博客地址:https://ainyi.com/67

java 开发 websocket 网页端聊天室的更多相关文章

  1. 分享基于 websocket 网页端聊天室

    博客地址:https://ainyi.com/67 有一个月没有写博客了,也是因为年前需求多.回家过春节的原因,现在返回北京的第二天,想想,应该也要分享技术专题的博客了!! 主题 基于 websock ...

  2. 如何利用WebSocket实现网页版聊天室

    花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...

  3. workerman-chat(PHP开发的基于Websocket协议的聊天室框架)(thinkphp也是支持socket聊天的)

    workerman-chat(PHP开发的基于Websocket协议的聊天室框架)(thinkphp也是支持socket聊天的) 一.总结 1.下面链接里面还有一个来聊的php聊天室源码可以学习 2. ...

  4. vue仿微信网页版|vue+web端聊天室|仿微信客户端vue版

    一.项目介绍 基于Vue2.5.6+Vuex+vue-cli+vue-router+vue-gemini-scrollbar+swiper+elementUI等技术混合架构开发的仿微信web端聊天室— ...

  5. 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室

    原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  6. 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室

    原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  7. 基于Node.js + WebSocket 的简易聊天室

    代码地址如下:http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.js ...

  8. XMPPFrameWork IOS 开发(六)聊天室

    原始地址:XMPPFrameWork IOS 开发(六)聊天室 聊天室 //初始化聊天室 XMPPJID *roomJID = [XMPPJID jidWithString:ROOM_JID]; xm ...

  9. JAVA实现webSocket网页聊天室

    一.什么是webSocket WebSocket 是一种网络通信协议,是持久化协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全 ...

随机推荐

  1. IE兼容问题 动态生成的节点IE浏览器无法触发

    ie下click()不能操作文档中没有的节点,所以你可以在click()前添加下面的语句 document.body.appendChild( input ); input.style.display ...

  2. 安装完Ubuntu后通过shell脚本一键安装软件

    安装完Ubuntu后通过shell脚本一键安装软件 以下代码中#是单行注释 :<<! ! 是多行注释. 运行的时候需要把多行注释去掉. 比如把以下代码保存为install.sh, 那么在终 ...

  3. How to setup Visual Studio without pain

    Visual Studio (VS) can be very hard to install. If you are lucky, one whole day may be enough to ins ...

  4. Centos7配置hadoop伪分布式

    修改hostname(可选) 通过下面命令查看hostname信息 hostnamectl 通过下面命令修改hostname hostnamectl set-hostname gy01 如图所示 下面 ...

  5. JS入门经典第四章总结

    charAt():该函数有一个参数,即选择哪一个位置上的参数.返回值就是该位置上的字符. charCodeAt():该函数有一个参数,即选择哪一个位置上的参数.返回值是该位置字符在Unicode字符集 ...

  6. Python mayavi库及mayavi管线

    Mayavi库的基本元素Mayavi库中主要有两大部分功能 一类是用于处理图形可视化和图形操作的mlab模块 一类是操作管线对象窗口对象的apimlab包含 绘图函数:实现已有的数据进行可视化显示,可 ...

  7. <笔记>TP5的save方法返回值

    用save方法来更新数据时,若更新前后数据没有改变则返回0,更新成功返回影响行数,更新失败返回false 若想要数据没改变时提示修改成功,则需要严格判断 if(结果!==false){提示成功}而不是 ...

  8. OPC上传ONENET工具

    这个去年做过比较死的 今年吸取人家转发网关配置工具的优点重做下

  9. 前端“黑话”polyfill

    前言 在Web前端开发这个日新月异的时代,总是需要阅读一些最新的英文技术博客来跟上技术的发展的潮流.而有时候会遇到一些比较高频的“黑话”,在社区里面可能已经是人人皆知的“共同语言”,而你接触的少就偏偏 ...

  10. BATJ等公司必问的8道Java经典面试题,你都会了吗?

    1.谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 考点分析: 对于这类笼统的问题,你需要尽量表现出自己的思维深入并系统化,Java 知识理解得也比较全面,一定要避免让面试官 ...