分享基于 websocket 网页端聊天室

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

有一个月没有写博客了,也是因为年前需求多、回家过春节的原因,现在返回北京的第二天,想想,应该也要分享技术专题的博客了!!

主题

基于 websocket 网页端聊天室

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

使用 java 开发后台

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

后台代码

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

前端代码

注意

前端需要实现这几个方法:

  // 注册事件
  // 监听打开连接
  ws.onopen = function(){
    openWs();
  };
  // 监听消息
  ws.onmessage = function(event){
    msgWs(event);
  };
  // 监听关闭连接
  ws.onclose = function(){
    closeWs();
  };
  // 监听发送错误
  ws.onerror = function(){
    errorWs();
  };

具体代码

<%@ 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="www.ainyi.com/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 = "wss://" + $(".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>

到这里大功告成

聊天方法

  1. 打开两个窗口输入项目地址进行聊天
  2. 可以把链接发给朋友打开,进行聊天

来一波截图

移动端

在线演示

PC 端:https://www.ainyi.com/krry_NetChat

移动端:https://www.ainyi.com/krry_NetChatPho

打完收工~

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

原文地址:https://www.cnblogs.com/ainyi/p/10398665.html

时间: 2024-10-06 20:24:18

分享基于 websocket 网页端聊天室的相关文章

.NET Core 基于Websocket的在线聊天室

什么是Websocket 我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后就会断开连接. 在没有websocket之前web系统如果要做双工通讯往往使用http long polling技术.http long polling 每次往服务器发送请求后,服务端不会立刻返回信息来结束请求,而是一直挂着直到有数据需要返回,或者等待超时了才会返回.客户端在结束上一次请求后立刻再发

Flask基于websocket的简单聊天室

1.安装gevent-websocket pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ gevent-websocket 2.chat.py文件内容如下: from flask import Flask,request,render_template import json from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import

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

一.项目介绍 基于Vue2.5.6+Vuex+vue-cli+vue-router+vue-gemini-scrollbar+swiper+elementUI等技术混合架构开发的仿微信web端聊天室——vueWebChat,实现了发送消息.表情(动图),图片.视频预览,右键菜单.截屏.截图可直接粘贴至文本框进行发送. 二.技术框架 MVVM框架:Vue2.5.6 状态管理:Vuex 页面路由:Vue-router iconfont图标:阿里巴巴字体图标库 自定义滚动条:vue-gemini-sc

基于Socket的Android聊天室

1        基于Socket的Android聊天室 Socket通信是网络通信中最常用的技术之一,通过Socket建立的可靠连接,可以让多个终端与服务器保持通信,最典型的应用是建立一个多人聊天程序.本实例使用ServerSocket建立聊天服务器.将服务器端所有的通讯线程保存到一个集合当中,当有用户发来数据,则转发给所有用户,实现聊天室效果.Android端通过使用Socket建立客户端链接,并且在AsyncTask中执行网络读写的任务,将用户输入的内容发送到服务器,并接收服务器发来的数据

Websocket网页间聊天

主要使用Websocket来和服务端进行通讯,后端的技术使用什么,都可以,比如mina,netty4.... Netty4实现Websocket网页间聊天 地址:http://my.oschina.net/u/1756290/blog/363247 说明下:该技术只支持HTML5,该技术现阶段并不是很成熟

基于WebSocket实现网页版聊天室

WebSocket ,HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,其使用简单,应用场景也广泛,不同开发语言都用种类繁多的实现,仅Java体系中,Tomcat,Jetty,Spring等都提供了对WS的API支持.本篇不做理论探究,仅自娱自乐,简单实现网页版的聊天室功能,在实际开发场景中变通使用即可.废话不叽歪,直接撸出来—— 1  简单页面 <!DOCTYPE html> <html lang="en"> <head> &l

nodejs 基于socket.io实现聊天室

由于之后要做的网页视频直播项目要用到socket.io模块,所以特地花时间研究了下,参照网上的代码做了些改进,自己写了个聊天室代码.不得不承认后端事实推送能力有点厉害,这是以前我用php一直苦恼的事情.下面简单介绍下我的项目,顺带讲解下nodejs. 事实上,在看别人写的代码之前,我一直不知道nodejs是干嘛的,直到真正接触到才明白这也可以算作是服务端代码,丰富的第三方库使其功能极其强大.它可以像golang的beego一样直接通过命令行开启服务器,不过要用到express模块.加载模块的方式

Html Websocket搭建右下角聊天室

最近闲来无事,为我的网站增加了聊天室功能,这里主要用到了websocket技术,这时html5的一种新技术 controller部分 package main.java.web.news; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; /** *

php+websocket搭建简易聊天室实践

1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短连接和长连接.短连接一般可以用ajax实现,长连接就是websocket.短连接实现起来比较简单,但是太过于消耗资源.websocket高效不过兼容存在点问题.websocket是html5的资源 如果想要详细了解websocket长连接的原理请看https://www.zhihu.com/ques