美文网首页
flask-websocket(3)历史消息持久化

flask-websocket(3)历史消息持久化

作者: 独步江雪 | 来源:发表于2020-02-17 03:21 被阅读0次

前端
app.py

from flask import Flask,render_template,request
import datetime

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')

@app.before_request
def before_request():
    for e in ['.css','.css/','.js','.js/']:
        if request.url.endswith(e):
            return

    with open('temp.log', 'a', encoding='utf-8') as f:
        f.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
        f.write('\n')
        f.write('ip:{}\n'.format(request.remote_addr))
        f.write('url:{}\n'.format(request.url))
        f.write('\n')

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5001, threaded=True)

templates/index.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <link rel="icon" href="/static/favicon.ico">
    <title>这个江湖</title>
    <style>
*{
    padding:0;
    margin:0;
}
.bg{
    position:fixed;
    z-index:0;
    background-image:url(/static/bg.jpg);
    width:100%;height:100%;
    background-size:cover;
}

input{
    box-sizing:border-box;
}

main{
    position:fixed;
    z-index:1;
    width:100%;
    max-width:500px;
    left:50%;
    transform:translateX(-50%);
    top:10%;
   background-color:rgba(255,255,255,1)
}

#content{
    //margin-top:30px;
    height:400px;
    border:1px solid black;
    overflow:auto;
}

#text{
    width:80%;
    float:left;
    height:25px;
}
#button-send{
    width:20%;
    float:left;
    height:25px;

}
    </style>
</head>
<body>

<div class="bg"></div>
<main>

    <div id="content"></div>
    <div class="bottom">
        <input type="text" id="name" placeholder="昵称">
        <button id="button-open">进入小木屋</button>
        <button id="button-close">离开小木屋</button>
        <div>
            <input type="text" id="text">
            <button id="button-send">发送</button>
        </div>
    </div>


</main>
<script>
Date.prototype.format = function (fmt) {
    var o = {
        "M+": this.getMonth() + 1, //月份
        "d+": this.getDate(), //日
        "H+": this.getHours(), //小时
        "m+": this.getMinutes(), //分
        "s+": this.getSeconds(), //秒
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度
        "S": this.getMilliseconds() //毫秒
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
    if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}

function current_time(){
    return new Date().format('yyyy-MM-dd HH:mm:ss');
}
</script>


<script>
var ws = null;
var name;

function setup_logined(is_login){
    if (is_login){
        document.getElementById('button-open').style.display = 'none';
        document.getElementById('button-close').style.display = 'inline-block';
        document.getElementById('name').readOnly='readOnly';

    }else{
        document.getElementById('button-open').style.display = 'inline-block';
        document.getElementById('button-close').style.display = 'none';
        document.getElementById('name').readOnly='';
    }
}

setup_logined(false);






document.getElementById('button-open').onclick = function(event){
    if (ws){
        return;
    }
    ws = new WebSocket('ws://www.wangsuyin.top:5002/echo');
    setup_logined(true)

    name = document.getElementById('name').value;

    ws.onopen = function(){
        console.log('web socket 已连接');
        ws.send( JSON.stringify({'type':'open', 'data':{'name':name}}));
    }
    ws.onmessage = function (event){
        var r_data = event.data; //接收到的数据
        show_message(r_data);
    }
    ws.onclose = function(){
        //alert('连接已关闭...');
    }

    html='<div style="color:green;"> 你推门而入!</div>';
    document.getElementById('content').innerHTML+= html  ;
    set_content_scroll_to_bottom();
}
document.getElementById('button-close').onclick = function(event){
    ws.close();
    ws=null;
    setup_logined(false);

    html='<div style="color:red;">你掩门而出!</div>';
    document.getElementById('content').innerHTML+= html  ;
    set_content_scroll_to_bottom();
}


function show_message(json_string){
    var json = JSON.parse(json_string);
    var type = json.type;
    var data = json.data;
    var html = '';
    if(type==='enter'){
        html='<div style="color:green;">' + data.name + ' 推门而入!</div>';
    }else if(type==='leave'){
        html='<div style="color:red;">' + data.name + ' 黯然离去,江湖上再不见此号人物……</div>';
    }else  if(type==='say'){
        console.log(data)
        html='<div>'+data.time+'  '+'<span style="color:#4096c1">'+ data.name+'</span>' + ' 说:'+data.content+'</div>';
    }if(type==='spacer'){
        html='<div style="margin:0 auto;text-align:center;color:gray;"> 江湖的风雨飘飘摇摇,只为你找来了这最近的一百条消息。</div>';
    }

    document.getElementById('content').innerHTML+= html  ;
    set_content_scroll_to_bottom();
}

function set_scroll_to_bottom(obj){
    obj.scrollTop = obj.scrollHeight;
}
function set_content_scroll_to_bottom(){
    set_scroll_to_bottom( document.getElementById('content'));
}

function send_message(){
    if (!ws){
        alert('请先进入聊天室');
        return;
    }
    var text =  document.getElementById('text').value ;
    ws.send( JSON.stringify({'type':'say', 'data':{'content':text}}));
    document.getElementById('content').innerHTML += '<div>'+ current_time() +'  '+ '<span style="color:#4096c1" >' +'我('+name+')' +'</span>'+ ': ' + text +'</div>';
    set_content_scroll_to_bottom();
}

document.getElementById('button-send').onclick = function(event){
    send_message();
}
document.getElementById('text').onkeypress = function(event){
    if ((event.which||e.keyCode)==13){
        send_message();
        event.target.value='';
        event.preventDefault();
    }

}



</script>
</body>
</html>

后端

import json
import time

from flask import Flask
from flask_sockets import Sockets

app = Flask(__name__)
sockets = Sockets(app)

ws_pool = []
history = []
with open('data/history.txt', 'r', encoding='utf-8') as f:
    content = f.read()
for e in [e for e in content.split('\n') if e]:
    history.append( json.loads(e))

#  ws://
@sockets.route('/echo')
def echo_socket(ws):
    r_data = ws.receive()
    r_data = json.loads(r_data)
    if not r_data['type'] == 'open':
        return
    name = r_data['data']['name']
    for e in ws_pool:
        try:
            e.send(json.dumps({'type': 'enter', 'data': {'name': name}}))
        except:
            ws_pool.remove(e)

    ws_pool.append(ws)

    # 推送历史消息
    for e in history[-100:]:
        ws.send(json.dumps({'type': 'say', 'data': e}))
    ws.send(json.dumps({'type': 'spacer', 'data': {'text':'以上是最近100条消息。'}}))


    while not ws.closed:
        r_data = ws.receive()

        if r_data is None:
            break
        # ws.send("客户端已收到: " + str(message))
        # 如何推送给其他人
        r_data = json.loads(r_data)
        if r_data['type'] == 'say':
            data = r_data['data']
            content = data['content']
            data_ = {
                'time': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())),
                'name': name,
                'content': content
            }
            history.append(data_)
            with open('data/history.txt', 'a', encoding='utf-8') as f:
                f.write(json.dumps(data_) +'\n')

            msg = json.dumps({'type': 'say', 'data': data_})


            for e in ws_pool:
                if e == ws:
                    continue
                e.send(msg)

    ws_pool.remove(ws)
    for e in ws_pool:
        e.send(json.dumps({'type': 'leave', 'data': {'name': name}}))


if __name__ == '__main__':
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler

    server = pywsgi.WSGIServer(('0.0.0.0', 5002), app, handler_class=WebSocketHandler)
    print('web server start ... ')
    server.serve_forever()

相关文章

网友评论

      本文标题:flask-websocket(3)历史消息持久化

      本文链接:https://www.haomeiwen.com/subject/uqvvfhtx.html