xiaoge-webscoketClient
一、简介
1.1、 什么是webSocket ?
websocket是一种网咯通信协议,它是html5开始提供的一种在单个tcp连接上进行的全双工通信的协议。
1.2 、什么是http协议 ?
http协议是一种无状态的、无连接的、单向的应用层协议采用请求、响应的模型通信只能由客户端发起,服务端对请求做出响应处理。
1.3、 http协议有什么缺陷 ?
1.3.1、http协议无法实现服务端主动向客户端发送消息
1.3.2、如果服务端由连续的状态变化,客户端想要获取变化就比较麻烦
1.3.3、大部分的web应用程序通过频繁的异步ajax请求实现长轮询
1.3.4、轮询的效率低,非常浪费资源
1.4为什么要有websocket协议 ?
webscoket协议就是为了解决http协议的部分缺陷,由HTML5开始提供。
1.5 、webSocket有什么优点 ?
1、Websocket连接允许客户端和服务端进行全双工通信,以便任何一方都可以通过建立的连接将数据推送到另一端
2、Websocket只需要建立一次连接,就可以一直保持连接状态,比轮询的效率高
二、webSocket 的实现
- webSocket的实现:
webSocket的实现是需要通过客户端和程序端两个对象来实现,客户端就是使用我们的js来实现的,而服务端我们使用Java代码创建一个服务来实现。
1、webSocket 客户端API
2.1.1、创建webSocket对象
//客户端创建websocket对象
//定义参数保存服务端访问路径
var url = "ws://47.105.83.87/WebSocket/server";
//创建websocket客户端对象
var ws = new WebScoket(url);
2.1.2、webSocket 的属性
属性 | 描述 |
---|---|
ws.readyState | 表示链接状态为只读状态,它可以由以下几个属性值 0:表示尚未建立连接 1:表示已经链接,可以通信 2:表示链接正在进行关闭状态 3:链接已经关闭 |
Ws.bufferedAmount | 只读,已被send()放入正在队列中等待传输,但是还没有发出的字节数 |
2.1.3、webSocket 的事件
事件名 | 描述 |
---|---|
Ws.onopen | 建立连接时触发执行 |
ws.onmessage | 客户端接受到服务端数据时触发执行 |
ws.onclose | 连接关闭时触发执行 |
ws.onerror | 通信发送错误时触发执行 |
2.1.4、webSocket 的方法
方法名 | 描述 |
---|---|
Ws.send() | 客户端向服务端发送消息 |
Ws.close() | 客户端关闭连接 |
2.1.5 webSocket客户端案例
<%@page import="com.xiaoge.model.UserInfo"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<base href="${pageContext.request.contextPath }/CheatRoom">
<meta charset="UTF-8">
<title>妞妞不哭聊天室</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="js/jquery-3.2.1.min.js" ></script>
<script type="text/javascript" src="js/xiaogemsg.js" ></script>
<style>
body{
margin: 0px;
padding: 0px;
height: 100%;
border: 1px solid gray;
border-radius: 10px;
}
.bottom-xia{
width: 100%;
position: relative;
border-radius: 10px;
border: 0px solid gray;
}
.bottom-xia-shang{
width: 100%;
border: 0px solid gray;
position: relative;
}
.bottom-xia-xia{
width: 100%;
height: 220px;
border: 0px solid red;
position: relative;
}
.bottom-xia-xia-shang{
width: 100%;
height: 170px;
border: 0px solid gray;
position: relative;
}
.bottom-xia-xia-xia{
width: 100%;
height: 50px;
border: 0px solid red;
position: relative;
}
.btngroup{
margin-top: 8px;
float: right;
}
.msg{
border-radius:5px ;
word-wrap:break-word;
font-size: 14px;
}
.msg-1{
margin-right: 50px;
text-align:center;
background-color: #FF8822;
}
.msg-2{
margin-left: 50px;
text-align:center;
background-color: lightskyblue;
}
.msgLeft{
clear: both;
float: left;
}
.msgRight{
clear: both;
float: right;
text-align: right;
}
#info{
width: 100%;
height: 388px;
border-radius: 5px;
border: 1px solid gainsboro;
overflow-y: auto;
}
.top-title{
height: 50px;
width: 100%;
border-radius: 10px;
border: 0px solid #FAEBCC;
background-color: #FAEBCC;
position: relative;
}
.top-title-name{
height:30px;
width:100%;
color: darkblue;
font-size:28px;
text-align:center;
font-family: '华文行楷';
border: 0px solid darkblue;
}
.top-title-num{
height:20px;
width:100%;
color: darkblue;
font-size:12px;
text-align:center;
font-family: '华文行楷';
border: 0px solid darkblue;
}
</style>
<script>
$(document).ready(function(){
// 创建websocket对象
var ws = new WebSocket("ws://47.105.83.87/WebSocket/server");
// 事件绑定 建立连接事件
ws.onopen = function(){
//给服务器发送信息
//ws.send("hello server!");
}
// 接受消息
ws.onmessage = function(evt){
//获取服务器端发送的消息
var dt = evt.data;
dt = JSON.parse(dt);
$("#onlineNum").text(dt.onlineNum)
var html = "<div class='msgLeft'>";
html += "<img src='img/"+dt.headerImg+"'style='width: 30px;height: 30px;' class='img-circle'/> <label>"+dt.userName+"</label><br/>";
html += "<div class='msg msg-2'>"+dt.txtmsg+"</div>";
html += "</div><br/>";
$("#info").append($(html)).scrollTop($('#info')[0].scrollHeight);
$('#chatAudio')[0].play();
}
//关闭事件
ws.onclose = function(){
xiaogemsg(200,"连接中断。。。",500);
ws.close();
}
ws.onerror = function(){
xiaogemsg(200,"网咯异常。。。",500);
ws.close();
}
$('#sendmsg').click(function(){
var txtmsg = $('#txt').val().trim();
var userName = $("#userName").val();
var headerImg =$("#headerImg").val();
var userId = $("#userId").val();
var dt ={"txtmsg":txtmsg,"userName":userName,"headerImg":headerImg,"userId":userId};
var data = JSON.stringify(dt);
if(txtmsg != ""){
var html = "<div class='msgRight'>";
html += "<label>"+userName+"</label> <img src='img/"+headerImg+"'style='width: 30px;height: 30px;' class='img-circle'/><br/>";
html += "<div class='msg msg-1'>"+txtmsg+"</div>";
html += "</div><br/>";
ws.send(data);
$("#info").append($(html)).scrollTop($('#info')[0].scrollHeight);
var txtmsg = $('#txt').val("");
}else{
xiaogemsg(200,"发送的内容不能为空",500);
}
});
//回车发送消息
$('body').bind('keyup', function(event) {
if (event.keyCode == "13") {
$('#sendmsg').click();
}
});
})
</script>
</head>
<body>
<input type="hidden" id="userName" value="${userInfo.userName}">
<input type="hidden" id="headerImg" value="${userInfo.headerImg}">
<input type="hidden" id="userId" value="${userInfo.userId }">
<input type="hidden" id="userPhone" value="${userInfo.userPhone}">
<audio autoplay="autoplay" id="chatAudio">
<source src="img/music/7821.wav" type="audio/mpeg">
</audio>
<div class="top-title">
<div class="top-title-name">
${userInfo.userName}<br>
</div>
<div class="top-title-num">
<label id="onlineNum" style="font-size: 12px;text-align: center;">离线</label>
</div>
</div>
<div class="bottom-xia">
<div id="info" class="bottom-xia-shang">
</div>
<div class="bottom-xia-xia">
<div class="bottom-xia-xia-shang">
<input type="text" id="txt" style="height: 100%;width: 100%;border: 1px solid gainsboro;" />
</div>
<div class="bottom-xia-xia-xia">
<div class="btngroup">
<div class="form-group">
<button id="sendmsg" type="button" id="login" class="btn btn-primary btn-block" style="float:left;width: 60px;">
发送
</button>
<a href="http://www.sugarguomur.com.cn/Online" target="_top" style="text-decoration: none;">
<button type="button" class="btn btn-danger btn-block" style="width: 60px;float:left;margin-left: 15px;">
关闭
</button>
</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
2、Java实现webSocket服务端
2.2.1 、java中webSocket的属性和方法:
在Java中,websocket的属性和方法和js中的使用相同,拥有的方法和属性一样,在2.1.2、2.1.3、2.1.4中有详细解说。
2.2.2 、Java实现websocket服务端案例(使用Tomcat )
*注意Tomcat必须使用Tomcat7或者以上的版本
package com.xiaoge.scoket;
import java.util.Set;
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;
@ServerEndpoint("/server")//发布为websocket类serverl为映射地址
public class WebScoketServer {
private static Set<Session> sockets = new CopyOnWriteArraySet<>();
private Session session;
//打开连接事件
@OnOpen
public void onOpen(Session session) throws Exception {
//System.out.println("有人连接了"+session.getId());
this.session = session;
sockets.add(session);
String msg = "{\"onlineNum\":\""+sockets.size()+"人在线\",\"txtmsg\":\"您好 ! 我是sugarguomur,欢迎光临! \",\"userName\":\"妞妞不哭\",\"headerImg\":\"xiaoge.jpg\"}";
this.session.getAsyncRemote().sendText(msg);
}
//收到消息
@OnMessage
public void onMessage(String msg) {
/*System.out.println("客户端来数据了"+msg);
this.session.getBasicRemote().sendText("你好客户端")同步发送
this.session.getAsyncRemote().sendText("你好客户端");*/
String id = session.getId();
//保存数据
msg = msg.substring(0,msg.length()-1)+",\"onlineNum\":\""+sockets.size()+"人在线\"}";
for(Session s : sockets) {
if(s.getId()!=id) {
s.getAsyncRemote().sendText(msg);
}
}
}
//关闭事件
@OnClose
public void onClose() {
//System.out.println("有人离开了"+session.getId());
sockets.remove(session);
}
//错误事件
@OnError
public void onError(Throwable error) {
System.out.println("网络异常"+error);
}
}