项目 08 WebSocket
项目班 08 WebSocket
app.py 更新 添加两个路由
handlers = [
('/', main.IndexHandler),
('/explore', main.ExploreHandler),
('/post/(?P<post_id>[0-9]+)', main.PostHandler),
('/upload', main.UploadHandler),
('/login', auth.LoginHandler),
('/logout', auth.LogoutHandler),
('/signup', auth.SignupHandler),
('/room', chat.RoomHandler),
('/ws', chat.ChatSocketHandler),
]
base.html 更新
{% block extra_scripts %}{% end %} #在body最后添加这一条
templates/message.html 添加HTML文件
<div class="message" id="m{{ message["id"] }}">{% module linkify(message["body"]) %}</div>
templates/room.html 添加聊天室html
{% extends 'base.html' %} {% block title %}room page{% end %} {% block content %} <div id="body">
<div id="inbox">
{% for message in messages %}
{% include "message.html" %}
{% end %}
</div>
<div id="input">
<form action="/a/message/new" method="post" id="messageform">
<table>
<tr>
<td><input name="body" id="message" style="width:500px"></td>
<td style="padding-left:5px">
<input type="submit" value="提交">
<input type="hidden" name="next" value="{{ request.path }}">
</td>
</tr>
</table>
</form>
</div>
</div>
{% end %} {% block extra_scripts %}
<script src="{{ static_url("js/chat.js") }}" type="text/javascript"></script>
{% end %}
handlers/chat.py 添加聊天的handlers
import logging
import tornado.escape
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import uuid from .main import AuthBaseHandler class RoomHandler(AuthBaseHandler):
"""
聊天室页面
"""
def get(self):
self.render("room.html", messages=ChatSocketHandler.cache) class ChatSocketHandler(tornado.websocket.WebSocketHandler):
waiters = set() # 等待接收信息的用户
cache = [] # 存放消息
cache_size = 200 # 消息列表的大小 def get_compression_options(self):
""" 非 None 的返回值开启压缩 """
return {} def open(self):
""" 新的WebSocket连接打开 """
logging.info("new connection %s" % self)
ChatSocketHandler.waiters.add(self) #在集合中添加用户,出现相同用户会去重 def on_close(self):
""" WebSocket连接断开 """
ChatSocketHandler.waiters.remove(self) #在集合中移除用户 @classmethod
def update_cache(cls, chat):
"""更新消息列表,加入新的消息"""
cls.cache.append(chat) #列表中添加消息
if len(cls.cache) > cls.cache_size:
cls.cache = cls.cache[-cls.cache_size:] #如果列表长度大于200个元素,只显示最后200个元素 [-200:-1] @classmethod
def send_updates(cls, chat):
"""给每个等待接收的用户发新的消息"""
logging.info("sending message to %d waiters", len(cls.waiters)) #logging类似于print,但又比print高级
for waiter in cls.waiters:
try:
waiter.write_message(chat) #给每个waiter发送消息
except:
logging.error("Error sending message", exc_info=True) def on_message(self, message):
""" WebSocket 服务端接收到消息 """
logging.info("got message %r", message)
parsed = tornado.escape.json_decode(message) #通过json解码message
chat = { #创建一个chat字典,id为不重复的uuid字符串,body为上面json解码后的一个body
"id": str(uuid.uuid4()),
"body": parsed["body"],
}
chat["html"] = tornado.escape.to_basestring(self.render_string("message.html", message=chat))
#将chat赋给message,放入message.html里面渲染后变成一个html代码,然后通过tornado自带to_basestring方法
#转化为chat字典中html键的值;render_string只会返回字节流,需要用to_basestring来转化 ChatSocketHandler.update_cache(chat) #执行更新消息列表函数
ChatSocketHandler.send_updates(chat) #执行发送消息函数
static/js/chat.js 添加chat.js文件
$(document).ready(function() {
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function() {}; $("#messageform").on("submit", function() { // 点击提交时执行
newMessage($(this));
return false;
});
$("#messageform").on("keypress", function(e) { // 回车提交时执行
if (e.keyCode == 13) {
newMessage($(this));
return false;
}
});
$("#message").select();
updater.start(); // 开始 WebSocket
}); function newMessage(form) { // 发送新消息给服务器
var message = form.formToDict();
updater.socket.send(JSON.stringify(message));
form.find("input[type=text]").val("").select();
} jQuery.fn.formToDict = function() {
var fields = this.serializeArray();
var json = {};
for (var i = 0; i < fields.length; i++) {
json[fields[i].name] = fields[i].value;
}
if (json.next) delete json.next;
return json;
}; var updater = {
socket: null, start: function() {
var url = "ws://" + location.host + "/ws";
updater.socket = new WebSocket(url); // 初始化 WebSocket
updater.socket.onmessage = function(event) { // 获取到服务器的信息时响应
updater.showMessage(JSON.parse(event.data));
}
}, showMessage: function(message) {
var existing = $("#m" + message.id);
if (existing.length > 0) return;
var node = $(message.html);
// node.hide();
$("#inbox").append(node); // 添加消息 DIV 到页面
// node.toggle();
}
};
项目 08 WebSocket的更多相关文章
- vue项目使用websocket做聊天项目总结
一.首先我们先了解一下websocket的使用: 1.创建websocket const ws = new WebSocket("ws://192.168.31.136:9998/ws&qu ...
- maven项目添加websocket
最近由于项目业务需求,需要用到websocket来实现即时信息的推送,学习了一下websocket,网上搜了一下学习教程,很多版本看的我云里雾里,最后选择用tomcat提供的最新版本(tomcat 启 ...
- vue项目使用websocket技术
一.为什么需要websocket? 前端和后端的交互模式最常见的就是前端发数据请求,从后端拿到数据后展示到页面中.如果前端不做操作,后端不能主动向前端推送数据,这也是http协议的缺陷. 因此,一种新 ...
- HTML5学习总结-08 WebSocket 服务器推送
一 WebSocket 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展 ...
- JAVAEE——BOS物流项目08:配置代理对象远程调用crm服务、查看定区中包含的分区、查看定区关联的客户
1 学习计划 1.定区关联客户 n 完善CRM服务中的客户查询方法 n 在BOS项目中配置代理对象远程调用crm服务 n 调整定区关联客户页面 n 实现定区关联客户 2.查看定区中包含的分区 n 页面 ...
- Java web项目使用webSocket
前端: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&qu ...
- Go语言【项目】 websocket消息服务
websocket消息服务 目的:搭建websocket服务,用浏览器与服务进行消息交互(写的第一个Go程序) 代码目录结构: 前端html页面: <!DOCTYPE html> < ...
- 开源项目 08 IOC Autofac
using Autofac; using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- AndroidAsync :异步Socket,http(client+server),websocket和socket.io的Android类库
AndroidAsync是一个用于Android应用的异步Socket,http(client+server),websocket和socket.io的类库.基于NIO,没有线程.它使用java.ni ...
随机推荐
- Simple Rtmp Server的安装与简单使用
Simple Rtmp Server是一个国人编写的开源的RTMP/HLS流媒体服务器. 功能与nginx-rtmp-module类似, 可以实现rtmp/hls的分发. 有关nginx-rtmp-m ...
- NOI2018网络同步赛游记
Day1 t1是一道NOI选手眼中的送分题,对于我来说还是有难度的,用了个把小时想了出来可持久化并查集的做法,最后一个点被卡常.赛后才发现Kruskal重构树是这样的简单.t2.t3由于我真的是太弱了 ...
- UnityShader实例15:屏幕特效之Bloom
http://blog.csdn.net/u011047171/article/details/48522073 Bloom特效 概述 Bloom,又称“全屏泛光”,是游戏中 ...
- box head上身旋转问题
现有资源: 1.可旋转上身的动画,旋转角度左右各90度. 2.下身没有旋转动画(腿部左转右转动画) 使用场景: 1.整个模型随鼠标位置旋转,不使用上身旋转动画. 缺点:人物转向动画僵硬. 解决方案: ...
- BZOJ2809:[APIO2012]dispatching
浅谈左偏树:https://www.cnblogs.com/AKMer/p/10246635.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php? ...
- 获得Azure订阅LoadBalancer的脚本
有客户希望可以通过一条命令获得一个Azure订阅中所有的负载均衡器. 目前在Azure的powershell中是没有这中命令的.但我们可以通过脚本的方式实现. 下面就是获得所有负载均衡的脚本: par ...
- java"=="与equals()方法的对照
总结:String s=new String(); s是在堆内存里的 String s2=new String(); s2是在堆内存又重新生成的一个. package com.da; //逆向思维:i ...
- 不支持PowerShell 2.0版本(don't support PowerShell version 2.0. )
在“程序包管理器控制台”使用命令“update-database”会提示:The Entity Framework Core Package Manager Console Tools don't s ...
- SVN客户端下载和Svn visual studio插件
1.Visual SVN Visual SVN visual studio插件 https://www.visualsvn.com/vis... 2.TortoiseSVN SVN客户端下载 http ...
- 使用struts2进行文件下载以及下载权限控制的例子
本测试有两个模块,一个是文件上上传,一个是文件下载,文件下载的时候会检查是否足有权限,如果没有,就会转发到登录页面,如果有权限,就会直接启动下载程序,给浏览器一个输出流. 下面直接上我的代码: 登录表 ...