基于WebSocket的简易聊天室
用的是Flash + WebSocket 哦~
一、项目结构:
二、导入模块
pip3 install gevent-websocket
三、先来看一个一对一聊天的代码
from flask import Flask, request, render_template from geventwebsocket.websocket import WebSocket from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer import json # 创建 flask 对象 app = Flask(__name__) # 跳转到所需 websocket 页面的视图函数 @app.route('/one-to-one') def one_to_one_page(): return render_template('one_to_one.html') # 用来存放一对一聊天用户的连接 格式: {用户名 : 连接对象, ...} one_to_one_user_dict = {} # 一对一聊天 @app.route('/one-to-one/<username>') def one_to_one(username): # 获取连接通道 user_socket = request.environ.get('wsgi.websocket') if not user_socket: return '请使用websocket连接 ' print(user_socket) one_to_one_user_dict[username] = user_socket while True: try: user_msg_json = user_socket.receive() user_msg = json.loads(user_msg_json) print(user_msg) # 如果发给的用户已连接,则发消息给对象 if user_msg['to_user'] in one_to_one_user_dict: user_msg['code'] = True one_to_one_user_dict[user_msg['to_user']].send(json.dumps(user_msg)) # 否则返回错误信息 else: msg = { 'code': False, 'msg': '用户未登录', } user_socket.send(json.dumps(msg)) except Exception as e: # 如果当前用户异常 将其从连接字典中删除 if username in one_to_one_user_dict: one_to_one_user_dict.pop(username) print(e) break if __name__ == '__main__': # 创建 wsgi server http_serv = WSGIServer(('0.0.0.0', 9527), app, handler_class=WebSocketHandler) # 持续运行 server http_serv.serve_forever()
在 one_to_one.html 页面里
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> #content { width: 100%; height: 200px; background-color: #e4e4e4; } #input { width: 100%; height: 50px; } .login { margin: 15px 0; } .self_info { color: #1004ff; } .self { margin-left: 100px; } .friend_info { color: red; } .friend { margin-right: 100px; } .friend_msg, .self_msg { width: 100%; } </style> </head> <body> <div class="container"> <div class="login"> <div class="form-inline"> <label for="in_login">用户名</label> <input id="in_login" type="text" class="form-control" placeholder="用户名"> <label for="friend_name">好友名称</label> <input id="friend_name" type="text" class="form-control" placeholder="好友名称"> <button id="b_login" type="submit" class="btn btn-default">Sign in</button> </div> </div> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-primary"> <div class="panel-heading"> 聊天室 </div> <div id="content" class="panel-body"> <div class="friend_msg clearfix hide" > <div class="pull-left friend"> <span class="friend_user">对方:</span> <span class="friend_info"> 你好! </span> </div> </div> <div class="self_msg clearfix hide"> <div class=" pull-right self"> <span class="self_info"> 你好 </span> <span class="self_user"> : 我</span> </div> </div> </div> </div> <div id="input"> <textarea id="input-info" class="form-control" rows="3"></textarea> <input id="submit" class="btn btn-default" type="submit" value="Submit"> </div> </div> </div> </div> </body> <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.js"></script> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script type="application/javascript"> var ws_url = 'ws://127.0.0.1:9527/one-to-one/'; var ws = null; {#var ws = new WebSocket('ws://127.0.0.1:9527/ws');#} {#ws.onopen = function () {#} {#ws.send('qweqwe')};#} //用户登录名 var login_user var friend_name //登录: $('#b_login').click(function () { var user = $('#in_login').val(); var friend = $('#friend_name').val(); console.log('user', user); if (! (user && friend) ) { alert('用户或好友不能为空!!!') } else { login_user = user friend_name = friend console.log(ws_url + login_user); ws = new WebSocket(ws_url + login_user); //接收信息 ws.onmessage = function (serv_msg) { serv_msg = JSON.parse(serv_msg.data) console.log('******secv********',serv_msg) if (serv_msg['code']){ var friend_info = serv_msg['send_msg']; var friend_user = serv_msg['send_user']; create_friend_msg(friend_info, friend_user) }else { alert(serv_msg['msg']) } }; } }); //发送信息 $('#submit').click(function () { var input_info = $('#input-info').val(); var send_msg_json = { send_user: login_user, to_user: friend_name, send_msg: input_info }; ws.send(JSON.stringify(send_msg_json)); console.log(JSON.stringify(send_msg_json)); create_self_msg(input_info); $('#input-info').val(''); }); //创建发出信息的标签 function create_self_msg(input_info) { var $self_msg = $('.self_msg').first().clone(); $self_msg.find('.self_info').text(input_info); $self_msg.find('.self_user').text(' : ' + login_user); $('#content').append($self_msg); }; //创建收到信息的标签 function create_friend_msg(friend_info, friend_user) { var $self_msg = $('.friend_msg').first().clone(); $self_msg.find('.friend_info').text(friend_info); $self_msg.find('.friend_user').text(friend_user + ' : '); $('#content').append($self_msg); }; </script> </html>
重点看其中的 script
<script type="application/javascript"> var ws_url = 'ws://127.0.0.1:9527/one-to-one/'; var ws = null; {#var ws = new WebSocket('ws://127.0.0.1:9527/ws');#} {#ws.onopen = function () {#} {#ws.send('qweqwe')};#} //用户登录名 var login_user var friend_name //登录: $('#b_login').click(function () { var user = $('#in_login').val(); var friend = $('#friend_name').val(); console.log('user', user); if (! (user && friend) ) { alert('用户或好友不能为空!!!') } else { login_user = user friend_name = friend console.log(ws_url + login_user); ws = new WebSocket(ws_url + login_user); //接收信息 ws.onmessage = function (serv_msg) { serv_msg = JSON.parse(serv_msg.data) console.log('******secv********',serv_msg) if (serv_msg['code']){ var friend_info = serv_msg['send_msg']; var friend_user = serv_msg['send_user']; create_friend_msg(friend_info, friend_user) }else { alert(serv_msg['msg']) } }; } }); //发送信息 $('#submit').click(function () { var input_info = $('#input-info').val(); var send_msg_json = { send_user: login_user, to_user: friend_name, send_msg: input_info }; ws.send(JSON.stringify(send_msg_json)); console.log(JSON.stringify(send_msg_json)); create_self_msg(input_info); $('#input-info').val(''); }); //创建发出信息的标签 function create_self_msg(input_info) { var $self_msg = $('.self_msg').first().clone(); $self_msg.find('.self_info').text(input_info); $self_msg.find('.self_user').text(' : ' + login_user); $('#content').append($self_msg); }; //创建收到信息的标签 function create_friend_msg(friend_info, friend_user) { var $self_msg = $('.friend_msg').first().clone(); $self_msg.find('.friend_info').text(friend_info); $self_msg.find('.friend_user').text(friend_user + ' : '); $('#content').append($self_msg); }; </script>
看看结果,个人感觉 还是没那么丑,有点样子的, 哈哈哈。。。
四、那多人聊天室:
app.py文件里的哦~
# 用来存放多人聊天用户的连接 格式: {用户名 : 连接对象, ...} conn_user_dict = {} # 多人聊天室 群聊 @app.route('/ws/<username>') def ws(username): # 获取连接通道 user_socket = request.environ.get('wsgi.websocket') if not user_socket: return '请使用websocket连接 ' conn_user_dict[username] = user_socket while True: try: user_msg_json = user_socket.receive() user_msg = json.loads(user_msg_json) # 遍历连接对象字典 for i in conn_user_dict: # 如果不是当前连接发送来的消息,就将消息发送给该连接对象 if not i == user_msg['send_user']: conn_user_dict[i].send(user_msg_json) except Exception as e: if username in conn_user_dict: conn_user_dict.pop(username) print(e) break
ws.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> #content { width: 100%; height: 200px; background-color: #e4e4e4; } #input { width: 100%; height: 50px; } .login { margin: 15px 0; } .self_info { color: #1004ff; } .self { margin-left: 100px; } .friend_info { color: red; } .friend { margin-right: 100px; } .friend_msg, .self_msg { width: 100%; } </style> </head> <body> <div class="container"> <div class="login"> <div class="form-inline"> <label for="in_login">用户名</label> <input id="in_login" type="text" class="form-control" placeholder="用户名"> <button id="b_login" type="submit" class="btn btn-default">Sign in</button> </div> </div> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-primary"> <div class="panel-heading"> 聊天室 </div> <div id="content" class="panel-body"> <div class="friend_msg clearfix"> <div class="pull-left friend"> <span class="friend_user">对方:</span> <span class="friend_info"> 你好! </span> </div> </div> <div class="self_msg clearfix"> <div class=" pull-right self"> <span class="self_info"> 你好 </span> <span class="self_user"> : 我</span> </div> </div> </div> </div> <div id="input"> <textarea id="input-info" class="form-control" rows="3"></textarea> <input id="submit" class="btn btn-default" type="submit" value="Submit"> </div> </div> </div> </div> </body> <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.js"></script> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script type="application/javascript"> var ws_url = 'ws://127.0.0.1:9527/ws/'; var ws = null; {#var ws = new WebSocket('ws://127.0.0.1:9527/ws');#} {#ws.onopen = function () {#} {#ws.send('qweqwe')};#} //用户登录名 var login_user //登录: $('#b_login').click(function () { var user = $('#in_login').val(); console.log('user', user); if (!user) { alert('用户名不能为空!!!') } else { login_user = user console.log(ws_url + login_user); ws = new WebSocket(ws_url + login_user); //接收信息 ws.onmessage = function (serv_msg) { serv_msg = JSON.parse(serv_msg.data) console.log('******secv********',serv_msg) var friend_info = serv_msg['send_msg']; var friend_user = serv_msg['send_user']; create_friend_msg(friend_info, friend_user) }; } }); //发送信息 $('#submit').click(function () { var input_info = $('#input-info').val(); var send_msg_json = { send_user: login_user, send_msg: input_info }; ws.send(JSON.stringify(send_msg_json)); console.log(JSON.stringify(send_msg_json)); create_self_msg(input_info); $('#input-info').val(''); }); //创建发出信息的标签 function create_self_msg(input_info) { var $self_msg = $('.self_msg').first().clone(); $self_msg.find('.self_info').text(input_info); $self_msg.find('.self_user').text(' : ' + login_user); $('#content').append($self_msg); }; //创建收到信息的标签 function create_friend_msg(friend_info, friend_user) { var $self_msg = $('.friend_msg').first().clone(); $self_msg.find('.friend_info').text(friend_info); $self_msg.find('.friend_user').text(friend_user + ' : '); $('#content').append($self_msg); }; </script> </html>