Django利用Channels+websocket开发聊天室

这篇具有很好参考价值的文章主要介绍了Django利用Channels+websocket开发聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、什么是Websocket?

2.Python-Django ASGI

3,Django开发聊天室或信息推送


前言

数据库系统课程设计要求,要开发一个B2B的售卖平台,本来开发浅薄的我,粗糙又基础的完成了一些基本的功能,想要开发一个单独的一对一聊天的功能(类似于微信这类),查阅了不少资料,依旧没思路,但是却知晓了服务器推送信息和聊天室的开发,记个笔记。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是Websocket?

1,Websocket的诞生背景:网站为了实现推送技术,用的基本是轮询,轮询是基于浏览器不断对服务器发出HTTP请求,服务器范围最新数据给客户端浏览器,这种模式缺点明显,带宽浪费严重,在这种背景下,HTML5诞生了Websocket协议,能更好的节省服务器资源并实现通讯。

2,WebSocket特点:WebSocket是单个TCP连接上的全双工通信,浏览器和服务器只需要完成一次握手,就可以创建持久性的连接,实现数据的双向传输。

2.Python-Django ASGI

1,WSGI:Python Web Server Gateway Interface,就是Web服务器网关接口,主要是规范了Web服务器和Web应用之间的交互,WSGI将Django分成了三类,服务器,APP,中间件。服务器就是用来监听某端口,APP用来调用某个函数,而中间件则位于两者中间,相当于一道门,起审核承接等作用。但是WSGI始终是为同步世界编写的,无法编写异步对象。因此,ASGI诞生了。

2,ASGI:Async Sever Gateway Interface,说白了,就是相当于WSGI+异步功能,而要调用WebSocket,Django就需要使用ASGI接口。

3,Django开发聊天室或信息推送

第一步:下载Channels模块

pip install channels

第二步:创建Django项目

Django-admin startproject websocket

创建后会看到Django3.0以后自存在asgi.py文件

Django利用Channels+websocket开发聊天室

第三步:创建一个APP应用

python manage.py startapp websocket_demo

第四步:进入settings.py模块,进行配置

首先在INSTALLED_APPS添加channels和websocket_demo

Django利用Channels+websocket开发聊天室

 然后添加再在settings中添加ASGI应用

Django利用Channels+websocket开发聊天室

 第五步:在创建的APP中创建routing.py文件以及进入asgi.py模块进行修改如下:

import os

from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from websocket_demo import routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web_socket.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": URLRouter(routing.websocket_urlpatterns),

})

图中代码很容易理解:将服务器的请求分成了两类,http请求则走默认的asgi APP流程,是Websocket请求则进入URL路由,即websocket_demo创建的routing.py文件

第六步,在websocket_demo的APP中views视图下创建chat.py并且配置routing.py的文件:

from django.urls import re_path
from websocket_demo.views import chat

websocket_urlpatterns = [
    re_path(r'chat/(?P<group>\w+)/$', chat.ChatConsumer.as_asgi()),
]

使用正则路径匹配chat/数字/的路径,是则进入chat.py文件中的CharConsumer函数

第七步,在urls.py中配置路由,指向websocket_demo中的chat.py文件

from django.urls import path, include
from websocket_demo.views import chat

urlpatterns = [
    path('index/', chat.chat)
]

第八步,编写chat.py文件的内容如下:

from django.shortcuts import render
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_sync
from datetime import datetime


def chat(request):
    group_number = request.GET.get('num')
    return render(request, 'web/index.html', context)




class ChatConsumer(WebsocketConsumer):

    def websocket_connect(self, message):
        self.accept()
        group = self.scope['url_route']['kwargs'].get("group")
        async_to_sync(self.channel_layer.group_add)(group, self.channel_name)

    def websocket_receive(self, message):
        group = self.scope['url_route']['kwargs'].get("group")
        async_to_sync(self.channel_layer.group_send)(group, {"type": "chat", 'message': message})

    def chat(self, event):
        text = event['message']['text']
        self.send(text)

    def websocket_disconnect(self, message):
        group = self.scope['url_route']['kwargs'].get("group")
        async_to_sync(self.channel_layer.group_discard)(group, self.channel_name)
        print('客户端断开连接了')
        raise StopConsumer()

首先第一个函数的意思是,进入index页面后会先进入chat函数,获取URL中请求的参数num,渲染到index.html页面,然后index.html页面使用javascript发起websocket请求,发起websocket请求后,ASGI服务器通过"websocket": URLRouter(routing.websocket_urlpatterns)路由访问routing文件,routing文件指向了ChatConsumer(WebsocketConsumer)类。

第二个函数ChatConsumer(WebsocketConsumer)类对websocket请求进行了处理,接收websocket的请求后获取组号即num的值,然后接收websocket发送的信息后调用chat函数将收到的信息同等的发送回去,websocket_disconnet则是客户端断开请求后触发的函数。

前端index.html的文件如下:

  reset.min.css文件:

html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}

style.css文件:

        

*, *:before, *:after {
  box-sizing: border-box;
}

:root {
  --white: #fff;
  --black: #000;
  --bg: #f8f8f8;
  --grey: #999;
  --dark: #1a1a1a;
  --light: #e6e6e6;
  --wrapper: 1000px;
  --blue: #00b0ff;
}

body {
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 400;
  background-image: url("../img/image.jpg");
  background-size: cover;
  background-repeat: none;
}

.wrapper {
  position: relative;
  left: 50%;
  width: var(--wrapper);
  height: 800px;
  -webkit-transform: translate(-50%, 0);
          transform: translate(-50%, 0);
}

.container {
  position: relative;
  top: 50%;
  left: 50%;
  width: 80%;
  height: 75%;
  background-color: var(--white);
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}
.container .left {
  float: left;
  width: 37.6%;
  height: 100%;
  border: 1px solid var(--light);
  background-color: var(--white);
}
.container .left .top {
  position: relative;
  width: 100%;
  height: 96px;
  padding: 29px;
}
.container .left .top:after {
  position: absolute;
  bottom: 0;
  left: 50%;
  display: block;
  width: 80%;
  height: 1px;
  content: '';
  background-color: var(--light);
  -webkit-transform: translate(-50%, 0);
          transform: translate(-50%, 0);
}
.container .left input {
  float: left;
  width: 188px;
  height: 42px;
  padding: 0 15px;
  border: 1px solid var(--light);
  background-color: #eceff1;
  border-radius: 21px;
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 400;
}
.container .left input:focus {
  outline: none;
}
.container .left a.search {
  display: block;
  float: left;
  width: 42px;
  height: 42px;
  margin-left: 10px;
  border: 1px solid var(--light);
  background-color: var(--blue);
  background-image: url("../img//name-type.png");
  background-repeat: no-repeat;
  background-position: top 12px left 14px;
  border-radius: 50%;
}
.container .left .people {
  margin-left: -1px;
  border-right: 1px solid var(--light);
  border-left: 1px solid var(--light);
  width: calc(100% + 2px);
}
.container .left .people .person {
  position: relative;
  width: 100%;
  padding: 12px 10% 16px;
  cursor: pointer;
  background-color: var(--white);
}
.container .left .people .person:after {
  position: absolute;
  bottom: 0;
  left: 50%;
  display: block;
  width: 80%;
  height: 1px;
  content: '';
  background-color: var(--light);
  -webkit-transform: translate(-50%, 0);
          transform: translate(-50%, 0);
}
.container .left .people .person img {
  float: left;
  width: 40px;
  height: 40px;
  margin-right: 12px;
  border-radius: 50%;
}
.container .left .people .person .name {
  font-size: 14px;
  line-height: 22px;
  color: var(--dark);
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 600;
}
.container .left .people .person .time {
  font-size: 14px;
  position: absolute;
  top: 16px;
  right: 10%;
  padding: 0 0 5px 5px;
  color: var(--grey);
  background-color: var(--white);
}
.container .left .people .person .preview {
  font-size: 14px;
  display: inline-block;
  overflow: hidden !important;
  width: 70%;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--grey);
}
.container .left .people .person.active, .container .left .people .person:hover {
  margin-top: -1px;
  margin-left: -1px;
  padding-top: 13px;
  border: 0;
  background-color: var(--blue);
  width: calc(100% + 2px);
  padding-left: calc(10% + 1px);
}
.container .left .people .person.active span, .container .left .people .person:hover span {
  color: var(--white);
  background: transparent;
}
.container .left .people .person.active:after, .container .left .people .person:hover:after {
  display: none;
}
.container .right {
  position: relative;
  float: left;
  width: 62.4%;
  height: 100%;
}
.container .right .top {
  width: 100%;
  height: 47px;
  padding: 15px 29px;
  background-color: #eceff1;
}
.container .right .top span {
  font-size: 15px;
  color: var(--grey);
}
.container .right .top span .name {
  color: var(--dark);
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 600;
}
.container .right .chat {
  position: relative;
  display: none;
  overflow: hidden;
  padding: 0 35px 92px;
  border-width: 1px 1px 1px 0;
  border-style: solid;
  border-color: var(--light);
  height: calc(100% - 48px);
  justify-content: flex-end;
  flex-direction: column;
}
.container .right .chat.active-chat {
  display: block;
  display: flex;
}
.container .right .chat.active-chat .bubble {
  transition-timing-function: cubic-bezier(0.4, -0.04, 1, 1);
}
.container .right .chat.active-chat .bubble:nth-of-type(1) {
  -webkit-animation-duration: 0.15s;
          animation-duration: 0.15s;
}
.container .right .chat.active-chat .bubble:nth-of-type(2) {
  -webkit-animation-duration: 0.3s;
          animation-duration: 0.3s;
}
.container .right .chat.active-chat .bubble:nth-of-type(3) {
  -webkit-animation-duration: 0.45s;
          animation-duration: 0.45s;
}
.container .right .chat.active-chat .bubble:nth-of-type(4) {
  -webkit-animation-duration: 0.6s;
          animation-duration: 0.6s;
}
.container .right .chat.active-chat .bubble:nth-of-type(5) {
  -webkit-animation-duration: 0.75s;
          animation-duration: 0.75s;
}
.container .right .chat.active-chat .bubble:nth-of-type(6) {
  -webkit-animation-duration: 0.9s;
          animation-duration: 0.9s;
}
.container .right .chat.active-chat .bubble:nth-of-type(7) {
  -webkit-animation-duration: 1.05s;
          animation-duration: 1.05s;
}
.container .right .chat.active-chat .bubble:nth-of-type(8) {
  -webkit-animation-duration: 1.2s;
          animation-duration: 1.2s;
}
.container .right .chat.active-chat .bubble:nth-of-type(9) {
  -webkit-animation-duration: 1.35s;
          animation-duration: 1.35s;
}
.container .right .chat.active-chat .bubble:nth-of-type(10) {
  -webkit-animation-duration: 1.5s;
          animation-duration: 1.5s;
}
.container .right .write {
  position: absolute;
  bottom: 29px;
  left: 30px;
  height: 42px;
  padding-left: 8px;
  border: 1px solid var(--light);
  background-color: #eceff1;
  width: calc(100% - 58px);
  border-radius: 5px;
}
.container .right .write input {
  font-size: 16px;
  float: left;
  width: 347px;
  height: 40px;
  padding: 0 10px;
  color: var(--dark);
  border: 0;
  outline: none;
  background-color: #eceff1;
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 400;
}
.container .right .write .write-link.attach:before {
  display: inline-block;
  float: left;
  width: 20px;
  height: 42px;
  content: '';
  background-image: url("../img/attachment.png");
  background-repeat: no-repeat;
  background-position: center;
}
.container .right .write .write-link.smiley:before {
  display: inline-block;
  float: left;
  width: 20px;
  height: 42px;
  content: '';
  background-image: url("../img/smiley.png");
  background-repeat: no-repeat;
  background-position: center;
}
.container .right .write .write-link.send:before {
  display: inline-block;
  float: left;
  width: 20px;
  height: 42px;
  margin-left: 11px;
  content: '';
  background-image: url("../img/send.png");
  background-repeat: no-repeat;
  background-position: center;
}
.container .right .bubble {
  font-size: 16px;
  position: relative;
  display: inline-block;
  clear: both;
  margin-bottom: 8px;
  padding: 13px 14px;
  vertical-align: top;
  border-radius: 5px;
}
.container .right .bubble:before {
  position: absolute;
  top: 19px;
  display: block;
  width: 8px;
  height: 6px;
  content: '\00a0';
  -webkit-transform: rotate(29deg) skew(-35deg);
          transform: rotate(29deg) skew(-35deg);
}
.container .right .bubble.you {
  float: left;
  color: var(--white);
  background-color: var(--blue);
  align-self: flex-start;
  -webkit-animation-name: slideFromLeft;
          animation-name: slideFromLeft;
}
.container .right .bubble.you:before {
  left: -3px;
  background-color: var(--blue);
}
.container .right .bubble.me {
  float: right;
  color: var(--dark);
  background-color: #eceff1;
  align-self: flex-end;
  -webkit-animation-name: slideFromRight;
          animation-name: slideFromRight;
}
.container .right .bubble.me:before {
  right: -3px;
  background-color: #eceff1;
}
.container .right .conversation-start {
  position: relative;
  width: 100%;
  margin-bottom: 27px;
  text-align: center;
}
.container .right .conversation-start span {
  font-size: 14px;
  display: inline-block;
  color: var(--grey);
}
.container .right .conversation-start span:before, .container .right .conversation-start span:after {
  position: absolute;
  top: 10px;
  display: inline-block;
  width: 30%;
  height: 1px;
  content: '';
  background-color: var(--light);
}
.container .right .conversation-start span:before {
  left: 0;
}
.container .right .conversation-start span:after {
  right: 0;
}

@keyframes slideFromLeft {
  0% {
    margin-left: -200px;
    opacity: 0;
  }
  100% {
    margin-left: 0;
    opacity: 1;
  }
}
@-webkit-keyframes slideFromLeft {
  0% {
    margin-left: -200px;
    opacity: 0;
  }
  100% {
    margin-left: 0;
    opacity: 1;
  }
}
@keyframes slideFromRight {
  0% {
    margin-right: -200px;
    opacity: 0;
  }
  100% {
    margin-right: 0;
    opacity: 1;
  }
}
@-webkit-keyframes slideFromRight {
  0% {
    margin-right: -200px;
    opacity: 0;
  }
  100% {
    margin-right: 0;
    opacity: 1;
  }
}

index.js文件:

                

document.querySelector('.chat[data-chat=person2]').classList.add('active-chat');
document.querySelector('.person[data-chat=person2]').classList.add('active');

var friends = {
  list: document.querySelector('ul.people'),
  all: document.querySelectorAll('.left .person'),
  name: '' },

chat = {
  container: document.querySelector('.container .right'),
  current: null,
  person: null,
  name: document.querySelector('.container .right .top .name') };


friends.all.forEach(function (f) {
  f.addEventListener('mousedown', function () {
    f.classList.contains('active') || setAciveChat(f);
  });
});

function setAciveChat(f) {
  friends.list.querySelector('.active').classList.remove('active');
  f.classList.add('active');
  chat.current = chat.container.querySelector('.active-chat');
  chat.person = f.getAttribute('data-chat');
  chat.current.classList.remove('active-chat');
  chat.container.querySelector('[data-chat="' + chat.person + '"]').classList.add('active-chat');
  friends.name = f.querySelector('.name').innerText;
  chat.name.innerHTML = friends.name;
}

index.html文件:

{% load static from static %}
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>聊天窗口界面</title>

<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600" rel="stylesheet">
<link rel="stylesheet" href="{% static 'web/chat/css/reset.min.css' %}">
<link rel="stylesheet" href="{% static 'web/chat/css/style.css' %}">

</head>
<body>

<div class="wrapper">
	<div class="container">
        <div class="left">
            <div class="top">
                <input type="text" placeholder="Search" />
                <a href="javascript:;" class="search"></a>
            </div>
            <ul class="people">
                <li class="person" data-chat="person2">
                    <img src="/static/myadmin/dist/img/user2-160x160.jpg" alt="" />
                    <span class="name">{{admin_name}}</span>
                    <span class="preview">I was wondering...</span>
                </li>
            </ul>
        </div>
        <div class="right">
            <div class="top"><span>To: <span class="name">{{admin_name}}</span></span></div>
            <div class="chat" data-chat="person2" id="chat-send" >
                <div class="conversation-start">
                    <span>{{time}}</span>
                </div>
            </div>
            <div class="write">
                <a href="javascript:;" class="write-link attach"></a>
                <input type="text" id="text"/>
                <a href="javascript:;" class="write-link smiley"></a>
                <a onclick="sendMessage()"  class="write-link send"></a>
            </div>
        </div>
    </div>
</div>

<script  src="{% static 'web/chat/js/index.js' %}"></script>
<script type="text/javascript">
    var socket=new WebSocket("ws://127.0.0.1:8000/chat/{{group_number}}/");
    socket.onopen = function(event)
	{
	var tag=document.getElementById("chat-send");
	var d=document.createElement("div");
	d.className="bubble you";
	d.innerHTML ="连接成功";
	tag.appendChild(d);
	}
    function sendMessage(){
	let text=document.getElementById("text");
	var tag=document.getElementById("chat-send");
	var d=document.createElement("div");
	d.className="bubble me";
	d.innerHTML =text.value;
	tag.appendChild(d);
	socket.send(text.value);
	text.value=" ";
	}
	socket.onclose = function(){
	var tag=document.getElementById("chat-send");
	var d=document.createElement("div");
	d.className="bubble you";
	d.innerHTML ="服务器主动断开连接";
	tag.appendChild(d);
}
socket.onmessage=function(event){
    var tag=document.getElementById("chat-send");
	var d=document.createElement("div");
	d.className="bubble you";
	d.innerHTML =event.data;
	tag.appendChild(d);
	}
</script>
<div style="text-align:center;margin:1px 0; font:normal 14px/24px 'MicroSoft YaHei';">
</div>
</body>
</html>

主要看javascript使用的函数,首先进行Websocket请ws://127.0.0.1:8000/chat/{{group_number}}/,然后分别的通过websocket发送信息,接受信息。

第九步,启动manage.py文件,同时打开两个页面观看效果:

        Django利用Channels+websocket开发聊天室

Django利用Channels+websocket开发聊天室

可以看到,某个用户发送的信息,将会被服务器发送到同一聊天室的所有客户端,实现了信息推送的功能。 

但是要实现一对一聊天的功能,目前实现是没有思路,有大神看到烦请指点指点。文章来源地址https://www.toymoban.com/news/detail-447886.html

到了这里,关于Django利用Channels+websocket开发聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • websocket网页聊天室

    实现websocket网页聊天室可以遵循以下步骤: 创建一个基于浏览器的WebSocket客户端,使用JavaScript。可以使用HTML5的WebSocket API。 编写服务器端的WebSocket应用程序,可以使用Node.js和WebSocket模块。 在服务器端创建一个WebSocket服务器,监听客户端请求,并将客户端与服务器端连接起

    2024年02月06日
    浏览(49)
  • 【WebSocket】SpringBoot整合WebSocket实现聊天室(一)

    目录 一、准备 1、引入依赖 2、创建配置类 二、相关注解 首先我们需要在项目中引入依赖,有两种方式。第一种我们可以在创建Spring Boot项目时搜索WebSocket然后勾选依赖 第二种是我们可以直接在项目的pom.xml文件中插入以下依赖 我们需要进行如下配置 ServerEndpointExporter 是一个

    2024年02月13日
    浏览(46)
  • 基于WebSocket的在线文字聊天室

    与Ajax不同,WebSocket可以使服务端主动向客户发送响应,本案例就是基于WebSocket的一个在线聊天室,不过功能比较简单,只能满足文字交流。演示如下。 案例学习于b站up主,链接 。这位up主讲的非常清楚,值得去学习。本文属于记录自我学习过程的文章。 项目目录下app.js 项

    2024年02月13日
    浏览(57)
  • Java+Vue实现聊天室(WebSocket进阶-聊天记录)

    WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服

    2024年02月11日
    浏览(61)
  • 在线聊天室(Vue+Springboot+WebSocket)

    实现了一个简单的在线聊天室的前后端。前端用Vue实现,后端用Springboot实现。         在线聊天室的功能包括创建用户和显示在线用户列表、发送消息和显示消息列表、用户和消息列表实时更新这几点。以下是整体功能的活动图: 用户身份         进入聊天室的用户需

    2024年01月15日
    浏览(49)
  • webSocket 聊天室 node.js 版

    全局安装vue脚手架  npm install @vue/cli -g 创建 vue3 + ts 脚手架  vue create vue3-chatroom src 同级目录下建 server:   核心代码: 完整代码:

    2024年02月12日
    浏览(48)
  • springboot+websocket实现简单的聊天室

    HTML HTML是创建和构造网页的标准标记语言。它使用一组标记标签描述网页上的内容结构。HTML文档由HTML元素的嵌套结构组成,每个元素由尖括号( )括起的标签表示。这些元素定义了网页的各个部分,如标题、段落、图像、链接、表单等。 JavaScript JavaScript是一种高级、解释性

    2024年01月21日
    浏览(57)
  • 基于springboot与websocket实现简易聊天室

    创建一个简单聊天室的HTML和JavaScript代码,匹配相应的css样式,这个聊天室将使用WebSocket技术,允许用户实时发送和接收消息。 1.1 html和js代码 通过new WebSocket(url)建立一个新的websocket连接。websocket连接建立之后使用websocket.onopen,websocket.onclose,websocket.onerror等方法实时监测we

    2024年02月01日
    浏览(52)
  • 【项目设计】基于WebSocket的Web聊天室

    本项目的名称为Web聊天室,即类QQ群组聊天,多个用户可以在同一个群组收发消息进行聊天 项目实现的业务 注册功能:用户输入账号,密码,昵称,图像点击即可注册用户(账号和昵称不能重复) 登陆功能:用户输入账号,密码即可进行登陆(如果登陆的账号已在别处登陆

    2023年04月18日
    浏览(115)
  • websocket+elementui+vue实现简易聊天室

    搭建服务端环境 安装socket.io 服务端基于node,js的express框架生成,所以写成模块,引入至app.js中 其中,io.sockets.emit用于向所有建立连接的客户端发送信息,socket.broadcast.emit用于向除发送方之外的客户端发送信息。 客户端基于vue和elementui 进入聊天页面后,先判断用户是否登录,

    2024年04月25日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包