项目 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 ...
随机推荐
- ACM学习历程—HDU1023 Train Problem II(递推 && 大数)
Description As we all know the Train Problem I, the boss of the Ignatius Train Station want to know ...
- nginx uwsgi wsgi django 这些东西究竟是什么关系
有太多的文章告诉我们nginx uwsgi django 这些东西怎么用了,太多的人知道这些东西的怎么使用,怎么配置,怎么优化,但是还是有一部分人比如我这种水货不知道这些东西到底是啥,为啥一个项目的发 ...
- 通过Jquery异步获取股票实时数据
最近朋友让我帮他做个异步获取数据的程序,暂时服务器什么都没有,所以我就想先拿股票数据打个框架,方便后续开发和移植等事情 代码如下: <!-- 说明:股票看盘 作者:黑桃A 时间:2014-04- ...
- BZOJ5281:[Usaco2018 Open]Talent Show
我对二分的理解:https://www.cnblogs.com/AKMer/p/9737477.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...
- 研华 RISC超低功耗3.5”单板电脑
产品简介: 这是一款搭载TI Sitara AM3358 Cortex-A8 1GHz高性能处理器的RISC 3.5”单板电脑.RSB-4221是一款稳定可靠.性能强大的低功耗平台,专为各种需要丰富I ...
- 创建Azure Blob Snapshot的脚本
在前面的文章中介绍了如何创建Azure Blob Snapshot.那篇文章中创建的脚本思路是:遍历所有Storage Account,找到所有vhd文件,进行Snapshot的创建. 但这种方式不够 ...
- JAVAset容器基本知识
import java.io.PrintWriter; import java.util.HashSet; import java.util.Scanner; import java.util.Ite ...
- k8s 基础 pod操作
创建hell world pod #vim hello-world-pod.yaml apiVersion: v1 kind: Pod metadata: name: hello-world spec ...
- linux 下 安装mysql
安装之前,因为redhat 是yum自带的,但是不能使用,因为要交钱,还要订阅,所以需要卸载,重新安装163提供的yum 在另外一篇文章介绍 yum list mysql* 列出所有关于mysal的安 ...
- Random简介
Random类 (java.util) Random类中实现的随机算法是伪随机,也就是有规则的随机.在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要 ...