前端
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()
网友评论