思路:
将websocket请求以 {name:socket} 存储到字典或mongodb,redis中;
while True建立通信循环
socket.receive()收消息
socket.send()发消息
json模块序列化返回的数据
服务端根据客户端消息判断聊天类型,并选择socket对象
客户端根据服务端的消息将信息展示在不同区域
代码
python:
from flask import Flask
from geventwebsocket. handler import WebSocketHandler
from geventwebsocket. server import WSGIServer
from flask import request
from geventwebsocket. websocket import WebSocket
from flask import render_template
from json import loads, dumps
app = Flask( __name__, template_folder= './templates' )
socket_dic = {
}
@app. route ( '/ws/' )
def ws ( username) :
sock = request. environ. get( 'wsgi.websocket' , None )
if not sock:
return '请使用ws链接'
socket_dic[ username] = sock
print ( socket_dic)
while True :
msg = sock. receive( )
if msg:
msg_dic = loads( msg)
to = msg_dic. get( 'to' )
data = msg_dic. get( 'data' )
host = msg_dic. get( 'host' )
if to:
if to in socket_dic. keys( ) :
socket_dic[ to] . send( dumps( {
'host' : host, 'data' : data, 'to' : to} ) )
sock. send( dumps( {
'host' : host, 'data' : data, 'to' : to} ) )
else :
continue
else :
for v in socket_dic. values( ) :
v. send( dumps( {
'host' : host, 'data' : data, 'to' : to} ) )
@app. route ( '/' )
def login ( ) :
return render_template( 'client.html' )
if __name__ == '__main__' :
http_server = WSGIServer( ( '127.0.0.1' , 5000 ) , app, handler_class= WebSocketHandler)
http_server. serve_forever( )
html
DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> client title>
< script src = " https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js" > script>
< script src = " https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js" > script>
< script src = " https://use.fontawesome.com/ada3f762c2.js" > script>
< link href = " https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel = " stylesheet" >
head>
< body>
{# 登录模块 #}
< div id = " login" class = " col-md-4 col-md-offset-4" >
< h1 class = " text-center" > 欢迎登录九聊! h1>
< p>
< span class = " text text-info" style = " font-size : 20px" > username: span> < input type = " text" id = " username" class = " form-control" >
p>
< button class = " btn btn-success text-center" id = " enter" > 进入聊天室 button>
div>
{# 聊天信息显示模块 #}
< div id = " home" >
div>
body>
< script>
let web= null ;
let loginEle= $ ( '#login' )
let sendEle= $ ( '#home' )
let enterEle= $ ( '#enter' ) . click ( function ( ) {
let username= $ ( '#username' ) . val ( ) . trim ( ) ;
web= new WebSocket ( 'ws://127.0.0.1:5000/ws/' + username)
loginEle. remove ( )
web. onopen = function ( ) {
alert ( username+ '欢迎来到久聊!' )
}
sendEle. html (
`
聊天室
发给:
消息:
发送
`
)
$ ( '#btn' ) . click ( function ( ) {
let toEle= $ ( '#to' )
let textEle= $ ( '#text' )
let toName= toEle. val ( ) . trim ( )
let data= textEle. val ( )
web. send ( JSON . stringify ( {
"to" : toName, "data" : data, 'host' : username} ) )
textEle. val ( '' )
} )
web. onmessage = function ( msg ) {
let s= msg. data;
let res= JSON . parse ( s)
let p = document. createElement ( 'p' ) ;
if ( res. to)
{
p. innerText= res. host+ '->' + res. to+ ':' + res. data
document. getElementById ( 'person' ) . appendChild ( p) ;
}
else
{
p. innerText= res. host+ ':' + res. data
document. getElementById ( 'content' ) . appendChild ( p) ;
}
}
} )
script>
html>
效果演示