《java websocket》之 实现
上一篇《java websocket》之 描述篇介绍了一下websocket,那么这一次就自己动手搭建一个属于自己的websocket。
真的挺简单的
环境描述:java jdk1.7+tomcat7.0x
第一步。创建一个干净的web project工程:
第二步。然后导入我们所用到的包:
第三步。创建一个websocket类用来实现接口,在创建一个POOL类用来扩展业务
废话不说直接上代码,相信我,我提供的代码直接复制进去就可以用!
WebSocket 类:
package websocket;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;public class WebSocket extends WebSocketServer {public WebSocket(InetSocketAddress address) {super(address);System.out.println("地址"+address);}public WebSocket(int port) throws UnknownHostException {super(new InetSocketAddress(port));System.out.println("端口"+port);}/*** 触发关闭事件*/@Overridepublic void onClose(org.java_websocket.WebSocket conn, int message,String reason, boolean remote) {userLeave(conn);}/*** 触发异常事件*/@Overridepublic void onError(org.java_websocket.WebSocket conn, Exception message) {System.out.println("Socket异常:"+message.toString());e++;}/*** 客户端发送消息到服务器时触发事件*/int j=0;int h=0;int e=0;int l=0;@Overridepublic void onMessage(org.java_websocket.WebSocket conn, String message) {message = message.toString();if(message!=null){//将用户加入this.userjoin(message.toString(), conn);}}/*** 触发连接事件*/@Overridepublic void onOpen(org.java_websocket.WebSocket conn, ClientHandshake handshake) {System.out.println("有人连接Socket conn:"+conn);l++;}/*** 用户加入处理* @param user*/public void userjoin(String user, org.java_websocket.WebSocket conn) {WebSocketPool.sendMessage(user); // 把当前用户加入到所有在线用户列表中String joinMsg = "[系统]"+user+"上线了!";WebSocketPool.sendMessage(joinMsg); // 向所有在线用户推送当前用户上线的消息WebSocketPool.addUser(user, conn); // 向连接池添加当前的连接对象WebSocketPool.sendMessageToUser(conn, WebSocketPool.getOnlineUser().toString()); // 向当前连接发送当前在线用户的列表}/*** 用户下线处理* @param user*/public void userLeave(org.java_websocket.WebSocket conn) {String user = WebSocketPool.getUserByKey(conn);boolean b = WebSocketPool.removeUser(conn); // 在连接池中移除连接if (b) {WebSocketPool.sendMessage(user.toString()); // 把当前用户从所有在线用户列表中删除String joinMsg = "[系统]"+user+"下线了";WebSocketPool.sendMessage(joinMsg); // 向在线用户发送当前用户退出的消息}}
}
WebSocketPool 类:
package websocket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.java_websocket.WebSocket;public class WebSocketPool {private static final Map<WebSocket, String> userconnections = new HashMap<WebSocket, String>();/*** 获取用户名* @param session*/public static String getUserByKey(WebSocket conn) {return userconnections.get(conn);}/*** 获取在线总数* @param*/public static int getUserCount() {return userconnections.size();}/*** 获取WebSocket* @param user*/public static WebSocket getWebSocketByUser(String user) {Set<WebSocket> keySet = userconnections.keySet();synchronized (keySet) {for (WebSocket conn : keySet) {String cuser = userconnections.get(conn);if (cuser.equals(user)) {return conn;}}}return null;}/*** 向连接池中添加连接* @param inbound*/public static void addUser(String user, WebSocket conn) {userconnections.put(conn, user); // 添加连接}/*** 获取所有的在线用户* @return*/public static Collection<String> getOnlineUser() {List<String> setUsers = new ArrayList<String>();Collection<String> setUser = userconnections.values();for (String u : setUser) {setUsers.add(u);}return setUsers;}/*** 移除连接池中的连接* @param inbound*/public static boolean removeUser(WebSocket conn) {if (userconnections.containsKey(conn)) {userconnections.remove(conn); // 移除连接return true;} else {return false;}}/*** 向特定的用户发送数据* @param user* @param message*/public static void sendMessageToUser(WebSocket conn, String message) {if (null != conn) {conn.send(message);}}/*** 向所有的用户发送消息* @param message*/public static void sendMessage(String message) {Set<WebSocket> keySet = userconnections.keySet();synchronized (keySet) {for (WebSocket conn : keySet) {String user = userconnections.get(conn);if (user != null) {conn.send(message);}}}}
}
然后让我们先测试一下是否行得通:
所以我在WebSocket 类里面写一个main方法来启动websocket服务:
public static void main(String[] args) throws InterruptedException {System.out.println("开始启动websocket");WebSocketImpl.DEBUG = false;int port = 8888; // 端口随便设置,只要不跟现有端口重复就可以WebSocket s = null;try {s = new WebSocket(port);} catch (UnknownHostException e) {System.out.println("启动websocket失败!");e.printStackTrace();}s.start();System.out.println("启动websocket成功!");}
启动成功后的样子
然后去http://www.blue-zero.com/websocket/ WebSocket在线测试
输入地址跟端口后,点击链接
那么到了这一步就说明你的websocket 已经搭建好了哦!恭喜你。
下面跟着作者把配置好的websocket实际应用到项目中。
第一步:技术点为:项目启动的时候启动配置好的服务。
因为启动项目就要开启websocket服务保持长连接状态。所以我们找到了web.xml,注意必须是3.0以上的
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><display-name></display-name> <filter><filter-name>startFilter</filter-name><filter-class>filter.startFilter</filter-class></filter><servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>servlet.TestServlet</servlet-class> </servlet><servlet-mapping><servlet-name>TestServlet</servlet-name><url-pattern>/TestServlet</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list>
</web-app>
创建startFilter (原谅我忘记大写开头,自己以打自己脸3次),以及TestServlet(不懂Servlet出门百度)
package filter;import java.io.IOException;
import java.net.UnknownHostException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;import org.java_websocket.WebSocketImpl;import websocket.WebSocket;/*** 创建人:晓枫 创建时间:2014年8月18日* @version*/
public class startFilter implements Filter {/*** 初始化*/public void init(FilterConfig fc) throws ServletException {this.startWebsocketOnline();}/*** 启动socket服务*/public void startWebsocketOnline() {System.out.println("开始启动websocket");WebSocketImpl.DEBUG = false;int port = 8888; // 端口随便设置,只要不跟现有端口重复就可以WebSocket s = null;try {s = new WebSocket(port);s.start();} catch (UnknownHostException e) {System.out.println("启动websocket失败!");e.printStackTrace();}System.out.println("启动websocket成功!");}public void destroy() {// TODO Auto-generated method stub}public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {// TODO Auto-generated method stub}}
细心地学者已经发现,实际上就是把main方法里面的代码拿过来了,霍哇啊哈哈哈哈哈哈!
TestServlet 类
package servlet;import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class TestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// TODO Auto-generated method stubsuper.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {System.out.println("content"+req.getParameter("content"));req.getSession().setAttribute("content", req.getParameter("content"));req.getRequestDispatcher("/index.jsp").forward(req, resp);}
}
到了这一步就基本服务端已经基本搭建好了。那么开始前台。技术为jsp页面+js
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>晓枫的WebSocket</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><script type="text/javascript" src="js/websocket.js"></script></head><body><input type="hidden" value="${content }" id="content"><form action="TestServlet" method="post">content : <input type="text" name="content"><button type="submit">登陆</button></form><span id="span"></span></body>
</html>
就简单的画了几个框框
(废话: 大部分人都有个毛病,就是功能做一半就会被别的事情所打扰,导致事情拖延,然后加班。就比如一个简单的页面就可以测试,非要写的那么华丽!作者我不管在哪个公司,很少加班,因为是后台,界面的好看与否,本身不算到工作量里面。达到目的就可以。如果嫌弃丑会再给你时间改的,不会加班)
websocket.js
/*** 申请一个WebSocket对象,参数是需要连接的服务器端的地址,* 同http协议使用http://开头一样,* WebSocket协议的URL使用ws://开头,* 另外安全的WebSocket协议使用wss://开头* 创建人:晓枫 创建时间 2016-8-18*/
var ws = new WebSocket("ws://127.0.0.1:8888");
ws.onopen = function()//当websocket创建成功时,即会触发onopen事件
{var content=document.getElementById("content").value;if(content==nullcontent==""){ws.send("XiaoFeng");//用于叫消息发送到服务端 注:此处为用户名}else{ws.send(content);}
};
ws.onmessage = function(evt)//当客户端收到服务端发来的消息时,会触发onmessage事件,参数evt.data中包含server传输过来的数据
{document.getElementById("span").innerHTML="当前在线人数为:"+evt.data;
};
ws.onclose = function(evt)//当客户端收到服务端发送的关闭连接的请求时,触发onclose事件
{alert("WebSocketClosed!");
};
ws.onerror = function(evt)//如果出现连接,处理,接收,发送数据失败的时候就会触发onerror事件
{alert("WebSocketError!");
};
到这里就可以结束了。
下面正式展示一下
我们打开多个页面来模仿多人连接.
我们输入一个内容
点击登录
已经可以看到这个用户信息添加到Map了
同时,别的页面也收到了提示消息!
那么到这里就基本结束了。
强制下线就是把连接移除掉,并且通知你的logout方法就可以了。
只能一个人登陆的话,就判断一下Map里面是否有用户就OK了!
实例就在这里,注释也都有,自己开脑洞吧。
支持单聊哦!方法已经写好了在Pool.自己发现吧
到这里开始要开始研究高并发了,可能会穿插一些spring实现之类的,看情况吧。
(下面看不看吧,压力测试一下)
在线测试的网站可以下载压力测试工具
然后稍微的修改一下代码。
然后启动服务器,清空控制台,设置好5000个客户端同时连接,连接成功后发送“1”,项目接收到后回复“2”,也就是说发送次数到为 连接数X2 的时候为一个不丢失, 越接近越好。
开始战斗吧!
额。。。。。。。。。。。。。。。。。。。。
呵呵。
作者: 手插口袋_
链接:http://www.imooc.com/article/12401
来源:慕课网
《java websocket》之 实现相关推荐
- Java Websocket实例【服务端与客户端实现全双工通讯】
Java Websocket实例[服务端与客户端实现全双工通讯] 现很多网站为了实现即时通讯,所用的技术都是轮询(polling).轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP ...
- java websocket 上传大文件,使用java websocket API和Javascript上传文件
我正在学习websocket并且已经使用websocket / json完成了聊天程序.但我坚持上传ATM的文件.任何建议&回答会很感激. 服务器端: package websocket; i ...
- WildFly上具有AngularJS的Java EE 7和Java WebSocket API(JSR 356)
这篇博客文章描述了用于WebSocket协议的Java API(JSR 356) (这是Java EE 7平台的四个最新JSR之一),并提供了部署在WildFly 8上并可以在OpenShift上在线 ...
- java乱码base64,解决 JAVA WebSocket 解析 base64 后中文字符串乱码
解决 JAVA WebSocket 解析 base64 后中文字符串乱码 解决 JAVA WebSocket 解析 base64 后中文字符串乱码 春风如贵客,一到便繁华.各位看官先赞再看,养成好习惯 ...
- java websocket 生存期_Java WebSocket生命周期
本章将讲述WebSocket端点的生命周期.WebSocket端点的生命周期为开发人员提供了一个框架来管理端点所需要的资源,也提供了一个框架来拦截消息.我们将仔细探讨其生命周期的顺序和语义,以及Jav ...
- Java WebSocket生命周期
为什么80%的码农都做不了架构师?>>> 本章将讲述WebSocket端点的生命周期.WebSocket端点的生命周期为开发人员提供了一个框架来管理端点所需要的资源,也提供了一 ...
- JSR 356 WebSocket (Java WebSocket 1.0) support is not available when running on Java 6. To suppress
tomcat异常,哪位大神给说说红色字体的异常的解决方法 [问题点数:20分] 不显示删除回复 显示所有回复 显示星级回复 显示得分回复 只显示楼主 收藏 关注 u014744615 那孩快跑 本版等 ...
- Java WebSocket编程与网页简易聊天室
在webSocket还未引入前,许多开发人员通过各种非正规手段来完成更新网站的最新信息和到所有当前访问者的任务,其中一种手段就是通过浏览器向服务器轮询更新,但这种手段的网络延迟比较明显,其用户体验比较 ...
- Java WebSocket 基础 建立端点
WebSocket协议的核心是使得两个对等节点间能够进行消息通信. 有两种Java WebSocket端点:注解式端点 和 编程式端点 <dependency><groupId> ...
- java websocket修改为同步_初级Java程序员需要掌握哪些主流技术才能拿25K?
某天,小五看到小丽愁眉苦脸的,于是问了她有什么心事~ 公司的社区网站访问越来越慢了,特别是搜索功能,这该怎么优化呀? 你们都用了啥技术搭建的呀? springboot+mybatis,数据库mysql ...
最新文章
- CentOS yum源的配置与使用
- 小问题: windows组件调用失败,无法加载安装安装程序:Wbemupgd.dll
- ssm使用全注解实现增删改查案例——DeptServiceImpl
- 从attention到Transformer+CV中的self-attention
- java中用I/O流实现文件上传
- GitHub 标星 10,000+,Apache 顶级项目 ShardingSphere 的开源之路
- Nginx安装手册,反向代理,负载均衡,keepalived高可用
- 英国航空系统周末故障,可能会损失掉全年将近 3% 的利润
- Python基础语法-05-装饰器
- 22_粗粒度权限控制
- Acronis Disk Director 11 Home下载,分区之王
- 关于WINDOWS超级终端的使用来调试MODEM 串口
- antd使用阿里巴巴矢量图标
- 车载娱乐系统开发术语记录
- 空格符号复制html,cf空格符号复制(cf空格代码)
- 求偶数c语言程序,用C语言编写一道程序计算100以内偶数的和
- 2018春节旅行大数据分析
- c++哈希(哈希表开散列实现)
- linux创建文件内容三行,Linux 文本处理三剑客
- Java基础笔记_6_类和对象_成员变量
热门文章
- matlab里的speed,matlab虚数 分析一下getspeed()函数
- Python3之模块及包的导入 import用法
- android 应用市场图尺寸,【干货】最新App应用市场截图尺寸大全
- 多层高速PCB设计不得不知道的那些事。1:多层板的设计原则
- PLC通过DDE通讯——基于Codesys和组态王7.5进行数据采集
- L.G.ALEXANDER 访谈录(ZT)
- TypeScript散文
- 如何更好地读开源软件之一:ERD工具简介
- [BZOJ4152][AMPPZ2014]The Captain题解
- 深处python漩涡中,谁能独善其身?