WebSocket给一个id发消息

首先简单介绍下WebSocket,WebSocket是HTML5中内容,是基于TCP的一种新的网络协议,它支持全双工、长连接的通信。在它出现之前,实时消息发送与接收通过轮询实现,但是频繁与服务器建立连接十分消耗资源。因此WebSocket出现了,在不断开连接的情况下,处于连接的用户可以任意发送消息,从而实现了在线聊天的功能。

因为我们JavaWeb课程作业是实现在线聊天功能,看到这题目我内心是崩溃的,不停百度,偶然发现Tomcat中自带了一个WebSocket的小例子, 有点小激动,运行一看,它竟然是群聊的。。。没办法,只好查看他的源代码,经过几天的推敲,终于看懂他的代码,并改写成一对一私聊。下面上代码 

[javascript] view plain copy
print ?
  1. var Chat = {};  
  2.     Chat.socket = null;  
  3.     // 创建一个websocket实例  
  4.     Chat.connect = (function(host) {  
  5.         if (‘WebSocket’ in window) {  
  6.             Chat.socket = new WebSocket(host);  
  7.         } else if (‘MozWebSocket’ in window) {  
  8.             Chat.socket = new MozWebSocket(host);  
  9.         } else {  
  10.             Console.log(’Console.log:你的浏览器不支持WebSocket’);  
  11.             return;  
  12.          }  
  13.         Chat.socket.onopen = function(){  
  14.              Console.log(’Console.log:WebSocket链接打开’);  
  15.              //按下回车键发送消息  
  16.              document.getElementById(’chat’).onkeydown = function(event) {  
  17.                  if (event.keyCode == 13) {  
  18.                      Chat.sendMessage();  
  19.                  }  
  20.              };  
  21.          };  
  22.          Chat.socket.onclose = function () {  
  23.              document.getElementById(’chat’).onkeydown = null;  
  24.              Console.log(’Console.log:WebSocket前端链接关闭’);  
  25.          };  
  26.          Chat.socket.onmessage = function (message) {  
  27.              Console.log(message.data);  
  28.          };  
  29.     });  
  30.     Chat.initialize = function() {  
  31.         //链接地址选择聊天页面的URL    
  32.         if (window.location.protocol == ‘http:’) {  
  33.             Chat.connect(”ws://” + window.location.host + “/onLineChat/index.jsp”);  
  34.         } else {  
  35.             Chat.connect(”wss://” + window.location.host + “/onLineChat/index.jsp”);  
  36.         }  
  37.     };  
  38.     //发送消息函数,后面动态添加了发送好友的唯一ID   
  39.     Chat.sendMessage = (function() {  
  40.         var fid = $(“#hidden-fid”).val();  
  41.         var messageContain = document.getElementById(‘chat’).value;  
  42.         var message = messageContain +“-“+fid;  
  43.         if(fid==“”){  
  44.             alert(”未选择发送消息的好友!”);  
  45.             return;  
  46.         }else{  
  47.             if (messageContain != “”) {  
  48.                 Chat.socket.send(message);  
  49.                 document.getElementById(’chat’).value = ;  
  50.             }else{  
  51.                 alert(”发送消息不能为空!”);  
  52.             }  
  53.         }  
  54.     });  
  55.      var Console = {};  
  56.      Console.log = (function(message) {  
  57.          var console = document.getElementById(‘console’);  
  58.          var p = document.createElement(‘p’);  
  59.          p.style.wordWrap = ’break-word’;  
  60.          p.innerHTML = message;  
  61.          console.appendChild(p);  
  62.          console.scrollTop = console.scrollHeight;  
  63.      });  
  64.     //初始化函数  
  65.      Chat.initialize();  
  66.      document.addEventListener(”DOMContentLoaded”function() {  
  67.          var noscripts = document.getElementsByClassName(“noscript”);  
  68.          for (var i = 0; i < noscripts.length; i++) {  
  69.              noscripts[i].parentNode.removeChild(noscripts[i]);  
  70.          }  
  71.      }, false);  
var Chat = {};
    Chat.socket = null;
    // 创建一个websocket实例
    Chat.connect = (function(host) {
        if ('WebSocket' in window) {
            Chat.socket = new WebSocket(host);
        } else if ('MozWebSocket' in window) {
            Chat.socket = new MozWebSocket(host);
        } else {
            Console.log('Console.log:你的浏览器不支持WebSocket');
            return;
         }
        Chat.socket.onopen = function(){
             Console.log('Console.log:WebSocket链接打开');
             //按下回车键发送消息
             document.getElementById('chat').onkeydown = function(event) {
                 if (event.keyCode == 13) {
                     Chat.sendMessage();
                 }
             };
         };
         Chat.socket.onclose = function () {
             document.getElementById('chat').onkeydown = null;
             Console.log('Console.log:WebSocket前端链接关闭');
         };
         Chat.socket.onmessage = function (message) {
             Console.log(message.data);
         };
    });
    Chat.initialize = function() {
        //链接地址选择聊天页面的URL  
        if (window.location.protocol == 'http:') {
            Chat.connect("ws://" + window.location.host + "/onLineChat/index.jsp");
        } else {
            Chat.connect("wss://" + window.location.host + "/onLineChat/index.jsp");
        }
    };
    //发送消息函数,后面动态添加了发送好友的唯一ID 
    Chat.sendMessage = (function() {
        var fid = $("#hidden-fid").val();
        var messageContain = document.getElementById('chat').value;
        var message = messageContain +"-"+fid;
        if(fid==""){
            alert("未选择发送消息的好友!");
            return;
        }else{
            if (messageContain != "") {
                Chat.socket.send(message);
                document.getElementById('chat').value = '';
            }else{
                alert("发送消息不能为空!");
            }
        }
    });
     var Console = {};
     Console.log = (function(message) {
         var console = document.getElementById('console');
         var p = document.createElement('p');
         p.style.wordWrap = 'break-word';
         p.innerHTML = message;
         console.appendChild(p);
         console.scrollTop = console.scrollHeight;
     });
    //初始化函数
     Chat.initialize();
     document.addEventListener("DOMContentLoaded", function() {
         var noscripts = document.getElementsByClassName("noscript");
         for (var i = 0; i < noscripts.length; i++) {
             noscripts[i].parentNode.removeChild(noscripts[i]);
         }
     }, false);

这是前端的JS代码,初始化WebSocket对象,监听对象的开启、关闭、发送消息等时间,将部分参数传给后台

  1. package websocket.chat;  
  2. import java.io.IOException;  
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5. import javax.servlet.http.HttpSession;  
  6. import javax.websocket.EndpointConfig;  
  7. import javax.websocket.OnClose;  
  8. import javax.websocket.OnError;  
  9. import javax.websocket.OnMessage;  
  10. import javax.websocket.OnOpen;  
  11. import javax.websocket.Session;  
  12. import javax.websocket.server.ServerEndpoint;  
  13.   
  14. import org.apache.juli.logging.Log;  
  15. import org.apache.juli.logging.LogFactory;  
  16.   
  17. import com.chat.common.HTMLFilter;  
  18. import com.chat.controller.UserDAOImpl;  
  19. import com.chat.entity.User;  
  20.   
  21. @ServerEndpoint(value = “/index.jsp”,configurator=GetHttpSessionConfigurator.class)  
  22. public class ChatAnnotation {  
  23.     private static final Log log = LogFactory.getLog(ChatAnnotation.class);  
  24.     private static final Map<String, ChatAnnotation> connection = new HashMap<String, ChatAnnotation>();  
  25.     private String userId;  
  26.     private String nickname;  
  27.     private Session session;  
  28.     public ChatAnnotation() {  
  29.     }  
  30.     @OnOpen  
  31.     public void start(Session session,EndpointConfig config) {  
  32.       //获取HttpSession对象  
  33.        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());  
  34.        User user = (User)httpSession.getAttribute(”user”);  
  35.        String uid = user.getId();  
  36.        this.nickname = user.getUsername();  
  37.        this.userId = uid;  
  38.          
  39.        this.session = session;  
  40.         /*判断链接是否已经在链接队列中,存在就不加*/  
  41.        if(!connection.containsKey(uid)){  
  42.            connection.put(uid, this);  
  43.            String message = ”* 你已经链接”;  
  44.            toConfirmFriend(message,userId);  
  45.        }  
  46.     }  
  47.     @OnClose  
  48.     public void end() {  
  49.         connection.remove(this.userId);  
  50.     }  
  51.     @OnMessage  
  52.     public void incoming(String message){  
  53.         String[] all = message.split(”-“);  
  54.         //要接收消息好友的ID  
  55.         String uid = all[1];  
  56.         //判断好友的连接是否存在,不存在就提示好友掉线  
  57.         if(connection.containsKey(uid)){  
  58.              String filteredMessage = String.format(”%s: %s”,  
  59.                         nickname, HTMLFilter.filter(all[0].toString()));  
  60.                 sendCommonRecord(filteredMessage,uid,this.userId);  
  61.         }else{  
  62.             ChatAnnotation client = connection.get(uid);  
  63.              String mes = String.format(”* %s %s”,  
  64.                      client.nickname, ”已经掉线!”);  
  65.             //将掉线信息发给自己  
  66.              toConfirmFriend(mes,this.userId);  
  67.         }  
  68.     }  
  69.     @OnError  
  70.     public void onError(Throwable t) throws Throwable {  
  71.         log.error(”Chat Error: ” + t.toString(), t);  
  72.     }  
  73.     //发送给指定的好友  
  74.     private static void toConfirmFriend(String msg,String uid) {  
  75.         ChatAnnotation client = connection.get(uid);  
  76.         try {  
  77.             synchronized (client) {  
  78.                 client.session.getBasicRemote().sendText(msg);  
  79.             }  
  80.         } catch (IOException e) {  
  81.             log.debug(”Chat Error: Failed to send message to ”+client.nickname, e);  
  82.             try {  
  83.                 client.session.close();  
  84.             } catch (IOException e1) {  
  85.                 // Ignore  
  86.             }  
  87.         }  
  88.     }  
  89.     //给聊天的双发发共同消息  
  90.     private static void sendCommonRecord(String msg,String sid,String gid) {  
  91.         ChatAnnotation client_send = connection.get(sid);  
  92.         ChatAnnotation client_get = connection.get(gid);  
  93.         try {  
  94.             synchronized (client_send) {  
  95.                 client_send.session.getBasicRemote().sendText(msg);  
  96.             }  
  97.             //将这条聊天记录保存在数据库  
  98.             UserDAOImpl userDAOImpl = new UserDAOImpl();  
  99.             userDAOImpl.saveCharRecord(msg, sid, gid);  
  100.         } catch (IOException e) {  
  101.             log.debug(”Chat Error: Failed to send message to ”+client_send.nickname, e);  
  102.             connection.remove(sid);  
  103.             try {  
  104.                 client_send.session.close();  
  105.             }catch (IOException e1) {  
  106.                 // Ignore  
  107.             }  
  108.         }  
  109.         try {  
  110.             synchronized (client_get) {  
  111.                 client_get.session.getBasicRemote().sendText(msg);  
  112.             }  
  113.         } catch (IOException e) {  
  114.             log.debug(”Chat Error: Failed to send message to ”+client_get.nickname, e);  
  115.             connection.remove(gid);  
  116.             try {  
  117.                 client_get.session.close();  
  118.             } catch (IOException e1) {  
  119.                 // Ignore  
  120.             }  
  121.         }  
  122.     }  
  123. }  
package websocket.chat;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
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;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

import com.chat.common.HTMLFilter;
import com.chat.controller.UserDAOImpl;
import com.chat.entity.User;

@ServerEndpoint(value = "/index.jsp",configurator=GetHttpSessionConfigurator.class)
public class ChatAnnotation {
    private static final Log log = LogFactory.getLog(ChatAnnotation.class);
    private static final Map<String, ChatAnnotation> connection = new HashMap<String, ChatAnnotation>();
    private String userId;
    private String nickname;
    private Session session;
    public ChatAnnotation() {
    }
    @OnOpen
    public void start(Session session,EndpointConfig config) {
      //获取HttpSession对象
       HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
       User user = (User)httpSession.getAttribute("user");
       String uid = user.getId();
       this.nickname = user.getUsername();
       this.userId = uid;

       this.session = session;
        /*判断链接是否已经在链接队列中,存在就不加*/
       if(!connection.containsKey(uid)){
           connection.put(uid, this);
           String message = "* 你已经链接";
           toConfirmFriend(message,userId);
       }
    }
    @OnClose
    public void end() {
        connection.remove(this.userId);
    }
    @OnMessage
    public void incoming(String message){
        String[] all = message.split("-");
        //要接收消息好友的ID
        String uid = all[1];
        //判断好友的连接是否存在,不存在就提示好友掉线
        if(connection.containsKey(uid)){
             String filteredMessage = String.format("%s: %s",
                        nickname, HTMLFilter.filter(all[0].toString()));
                sendCommonRecord(filteredMessage,uid,this.userId);
        }else{
            ChatAnnotation client = connection.get(uid);
             String mes = String.format("* %s %s",
                     client.nickname, "已经掉线!");
            //将掉线信息发给自己
             toConfirmFriend(mes,this.userId);
        }
    }
    @OnError
    public void onError(Throwable t) throws Throwable {
        log.error("Chat Error: " + t.toString(), t);
    }
    //发送给指定的好友
    private static void toConfirmFriend(String msg,String uid) {
        ChatAnnotation client = connection.get(uid);
        try {
            synchronized (client) {
                client.session.getBasicRemote().sendText(msg);
            }
        } catch (IOException e) {
            log.debug("Chat Error: Failed to send message to "+client.nickname, e);
            try {
                client.session.close();
            } catch (IOException e1) {
                // Ignore
            }
        }
    }
    //给聊天的双发发共同消息
    private static void sendCommonRecord(String msg,String sid,String gid) {
        ChatAnnotation client_send = connection.get(sid);
        ChatAnnotation client_get = connection.get(gid);
        try {
            synchronized (client_send) {
                client_send.session.getBasicRemote().sendText(msg);
            }
            //将这条聊天记录保存在数据库
            UserDAOImpl userDAOImpl = new UserDAOImpl();
            userDAOImpl.saveCharRecord(msg, sid, gid);
        } catch (IOException e) {
            log.debug("Chat Error: Failed to send message to "+client_send.nickname, e);
            connection.remove(sid);
            try {
                client_send.session.close();
            }catch (IOException e1) {
                // Ignore
            }
        }
        try {
            synchronized (client_get) {
                client_get.session.getBasicRemote().sendText(msg);
            }
        } catch (IOException e) {
            log.debug("Chat Error: Failed to send message to "+client_get.nickname, e);
            connection.remove(gid);
            try {
                client_get.session.close();
            } catch (IOException e1) {
                // Ignore
            }
        }
    }
}

这是后台代码,使用注解方式监听前台的事件

重点:
1)Tomcat中connection是一个set,此处改写成了map,键名保存用户的唯一ID,键值保存用户连接对象,所以只要确定了用户ID,就能向该用户发送消息。创建连接向map中添加,断开链接从map中移除。
2)如何将用户ID从前台传到后台,这里有两种方法,借鉴了这篇博客  http://blog.csdn.net/qq_33171970/article/details/55001587
采用HttpSession的方法在ChatAnnotation中访问session的属性
3)前台发送消息,动态将发送消息的接受者ID加在消息内容结尾,后台接收到数据,将消息内容和用户ID分离开
4)改写发送消息的方法,实现向特定好友发送消息,方法是根据已经传过来的好友ID,从Map中获取指定的连接对象,调用该对象的sendText(msg);方法实现私聊。
5)因为有个导出聊天记录的功能,所以,每发送成功一条消息,这条消息将被存进数据库,永久记录下来。

/****************************************************************************************************************************************/
这个是项目的完成图,已经实现了,前端是模仿网页版微信的。。。。

留言后任意转载

                </div>
好的,以下是一个简单的 WebSocket 聊天的示例代码: HTML 代码: ```html <!DOCTYPE html> <html> <head> <title>WebSocket 聊天室</title> </head> <body> <div id="chat"></div> <form id="chat-form"> <input type="text" id="chat-input" placeholder="输入消息"> <button type="submit">发送</button> </form> <script> const chat = document.getElementById('chat'); const form = document.getElementById('chat-form'); const input = document.getElementById('chat-input'); // 创建 WebSocket 连接 const socket = new WebSocket('ws://localhost:3000'); // 监听消息 socket.onmessage = (event) => { const message = event.data; const p = document.createElement('p'); p.innerText = message; chat.appendChild(p); }; // 监听表单提交事件 form.addEventListener('submit', (event) => { event.preventDefault(); const message = input.value; socket.send(message); input.value = ''; }); </script> </body> </html> ``` Node.js 服务器代码: ```javascript const WebSocket = require('ws'); // 创建 WebSocket 服务器 const wss = new WebSocket.Server({ port: 3000 }); // 监听连接事件 wss.on('connection', (ws) => { console.log('客户端已连接'); // 监听消息事件 ws.on('message', (message) => { console.log(`接收到消息:${message}`); // 广播消息给所有客户端 wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); } }); }); }); ``` 这段代码创建了一个 WebSocket 服务器,当客户端连接时,服务器会将消息广播给所有客户端。在客户端,创建了一个 WebSocket 连接,当表单提交时,将消息发送给服务器服务器收到消息后,会广播给所有客户端。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值