关于websocket自定义通信,聊天工具--博客园老牛大讲堂

声明: 我的文章会不断更新的,或许你今天看完后,我第二天就更新了。关注:博客园老牛大讲堂

    关于websocket通信,我也没做过,我也是参考别人的才成功的!今天把文章给补全。参考地址(我也忘了,有空补上)。

    首先jdk1.7和tomact7以上,才能用websocket. 并且需要jar包:websocket-api.jar

1、什么是websocket通信?

  通信一般应用就是常见的聊天等软件。例如qq,微信等。

2、websocket有什么作用?

   其实说白了,就是为了进行聊天的,或者实现群聊。如果你能把这一块儿做全了,那么你也可以推出一个聊天工具了。

3、常见的通信有哪几种?

  通信分类:

    1、现在网上出了很多第三方的通信。个人推荐这种。(毕竟人家的东西已经成熟),用着方便。(第三方通信)

    2、另一种就是andorid原生开发了。应该也是借用第三方的通信(个人表示不清楚)(android通信)

    3、如果你是一个H5用户,又不想借用第三方通信,那么就可以往下面看了。(例如:websocket)。(自定义消息通信)

  补充:

    1、对于android来说,一般用第三方通信:例如极光,融云等平台。

    2、对于H5用户来说,一般也用第三方通信,也可以用websocket。

4、自定义消息通信怎样实现?(其他两种我就不介绍了)

  接下来我介绍一种推送,它不借助与第三方工具是第三种情况。

  1、MyWebSocket代码:

package Tools;
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("/chat")//这里的注释相当于web.xml了,所以可以不用配置web.xml了,当然配置了也不算错
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());
        
//       this.session.getBasicRemote().sendText(HttpServletRequest.getRemoteAddr());---博客园老牛大讲堂
    }
     
    /**
     * 连接关闭调用的方法
     */
    @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--;
    }
}

  2、前端页面

  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>
<html>
  <head>
  	<script type="text/javascript" src="js/jquery.min.js"></script>
    <base href="<%=basePath%>">
    <title>My WebSocket</title>
  </head>
   
  <body>
    Welcome<br/>
    <input id="text" type="text" /><button onclick="send()">Send</button>    <button onclick="closeWebSocket()">Close</button>
    <div id="message">
    </div>
  </body>
   
  <script type="text/JavaScript">
      var websocket = null;
       
      //判断当前浏览器是否支持WebSocket
      if('WebSocket' in window){
          websocket = new WebSocket("ws://localhost:8080/MyWebSocket/chat");//这里没有走web.xml,直接到了MyWebSocket
      }
      else{
          alert('Not support websocket');
      }
       
      //连接发生错误的回调方法
      websocket.onerror = function(){
          setMessageInnerHTML("error");
      };
       
      //连接成功建立的回调方法
      websocket.onopen = function(event){
          setMessageInnerHTML("open");
      };
       
      //接收到消息的回调方法
      websocket.onmessage = function(){
          setMessageInnerHTML(event.data);
      };
       
      //连接关闭的回调方法
      websocket.onclose = function(){
          setMessageInnerHTML("close");
      };
       
      //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
      window.onbeforeunload = function(){
          websocket.close();
      };
       
      //将消息显示在网页上
      function setMessageInnerHTML(innerHTML){
          document.getElementById('message').innerHTML += innerHTML + '<br/>';
      }
       
      //关闭连接
      function closeWebSocket(){
          websocket.close();
      }
       
      //发送消息
      function send(){
          var message = document.getElementById('text').value;
          websocket.send(message);
      }
  </script>
  <body>sds</body>
</html>

  3、web.xml可以不配置的(我的没有配置并且成功了)

  注释:如果不成功,给我留言。(稍后我会上传我自己写的一个网页版的群聊软件)

 5、webSocek群聊天工具(改进版)--博客园老牛大讲堂。

  思路:用户都通过键值对的方式进行传递数据和内容。(这样就可以传递不同数据)

     其中 ,是我自己在里面封装的方法,你们可以自己写的。

  这个例子,重要的是一个思路。

  后端代码不变!前端页面部分:--博客园老牛大讲堂

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"><meta name="format-detection" content="telephone=no">
    <title>chat</title>
    <link rel="stylesheet" href="../../css/seedsui.min.css">//引入的第三方的css
    <script src="../../js/seedsui.min.js"></script>//引入的第三方的js
    <script type="text/javascript" src="../../js/swiperJs/jquery.min.js" ></script>
    <script type="text/javascript" src="../../js/myJs/check.js" ></script>//自己定义的方法-博客园老牛大讲堂。
    <script type="text/javascript" src="../../js/myJs/jsoup.js" ></script>//自己定义的方法
    <style>
    	.niu-pandding-left-30{
    		padding-left: 30px;
    	}
    	
    	.niu-user-font{
    		font-size: 14px;
    		text-align: center;
    		margin: 15px 40px 15px 0px;
    		float: right;
    	}
    	.niu-huanying{
    		font-size: 14px;
    		text-align: center;
    		margin: 15px 40px 15px 0px;
    	}
    	.niu-button{
    		padding-left: 10px;
    	}
    </style>
</head>
//博客园老牛大讲堂
	<body ontouchstart="">
        <header>
            <div class="titlebar niu-pandding-left-30">
                <h1>内部讨论组</h1>
            </div>
        </header>
        <article style="padding-bottom:47px;">
        	<p class="niu-user-font" >时间:<span id="shijian">2017-04-24 9:40:26</span></p>
        	<br />
            <ul class="chat" id="niuChat">
                <li>
                    <div class="chat-photo">
                        <img src="../../img/photo.png" alt="male">
                    </div>
                    <div class="chat-content-box">
                        <div class="chat-content">
                        	<b>用户ID:<span>sadf</span></b>
                            <p>啥?你说滴是啥?那啥啥啥东西啊?咋看不懂啊,你说滴到底是个啥?</p>
                        </div>
                    </div>
                </li>
                 <li class="even">
                    <div class="chat-photo">
                        <img src="../../img/photo.png" alt="Female">
                    </div>
                    <div class="chat-content-box">
                        <div class="chat-content">
                            <p>啥?你说滴是啥?那啥啥啥东西啊?咋看不懂啊,你说滴到底是个啥?</p>
                        </div>
                    </div>
                </li>
            </ul>
        </article>
        <footer>
           <div class="inputbox bordered margin8">
           		<a class="button niu-button">请输入内容:</a>
				<input type="text" class="input-text" id="NiuContent"/>
				<a class="button lrpadding8" onclick="send()">检验</a>
			</div>
        </footer>
    
    	<script>
       		
       		var name="老师";
       		
       		//时间初始化模块
       		clearUI();
       		function clearUI(){
       			$("#niuChat").empty();//清空内容
				setInterval(function(){
					$("#shijian").html("2016-05-04 14:12:12"));//主要实现显示时间,你也可以自己写个方法,动态的得到时间
				}, 1000)
       		}
       		
       		var websocket = null;
		     //判断当前浏览器是否支持WebSocket
		    if('WebSocket' in window){
		       websocket = new WebSocket("ws://localhost:8080/SecondWeb/chat");//这个是你后台写的webSocket.
		    }else{
		        alert('你的浏览器不支持通信');
		    }
		      	
		    //连接成功建立的回调方法
			websocket.onopen = function(event){
			    setTimeout(function(){
       				websocket.send("name:"+name);//发送一句话,key值是name,把用户的名字发送给后台,这样大家都能看到你是谁了。
       			},4000);
      		};

			//接收到消息的回调方法--博客园老牛大讲堂。
		    websocket.onmessage = function(){
		      	var value=fenge(event.data);//当服务器有返回值则,自动调用这个方法,event.data是服务器的数据。--博客园老牛大讲堂
		        //每当我发送消息,成功的话,服务器端就会返回信息,那么我就可以根据key值不同,得到不同的内容了。---- 博客园老牛大讲堂
		      	if(value[0]=="name"){
		      		var str=' <p class="niu-huanying">欢迎老师:《<span>'+value[1]+'</span>》进入房间</p><br/>';
		      		$("#niuChat").append(str);//当这个人进入房间,动态添加数据
		      	}else if(value[0]=="close"){
		      		var str=' <p class="niu-huanying">《<span>'+value[1]+'</span>》老师已经离开了房间</p><br>';
		      		$("#niuChat").append(str);//当老师退出房间,进行提示离开房间
		      	}
				else if(value[0]=="closeAll"){
//		      		console.log(value[0]+value[1]);	
		      	}
				else if(value[0]=="content"){
		      		var str=' <li><div class="chat-photo"><img src="../../img/photo.png" alt="male"></div>'+
                    		'<div class="chat-content-box"><div class="chat-content"><span><'+name+'老师></span></b>'+
                            '<p>'+value[1]+'</p></div></div></li>';
		      		$("#niuChat").append(str);//当某个用户发送内容,那么本页面进行信息的显示。
		      	}
		    };
		    
		      //连接关闭的回调方法--博客园老牛大讲堂
		      websocket.onclose = function(){
		          websocket.send("close:"+name);
		      };
		       
		      //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
		      window.onbeforeunload = function(){
		      	websocket.send("close:"+name)//关闭连接,发送key值是close的内容。
		         websocket.close();
		      };
		       
		      //关闭连接--博客园老牛大讲堂
		      function closeWebSocket(){
		      	websocket.send("close:"+name)
		        websocket.close();
		      }
		      
		      $(document).keydown(function(event){ 
					if(event.keyCode == 13){ 
						send();//当我敲击键盘空格键,那么进行发消息的内容。
					}
				});
		      
		      
		      //发送消息--博客园老牛大讲堂
		     function send(){
		     	var str=$("#NiuContent").val()+"";//进行输入框清空操作。
		     	if(str!=""){
		     		$("#NiuContent").val("");
		     		websocket.send("content:"+str);//向服务器发送内容。
		     	}else{
		     		$("#NiuContent").attr("placeholder","内容不能为空");
		     	}
      		}
//对key值和value值根据:号进行数据的分割。---博客园老牛大讲堂 function fenge(str){ return str.split(":"); } </script> </body> </html>

  

原文地址:https://www.cnblogs.com/laonniudajiangtang/p/6514226.html