项目班 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的更多相关文章

  1. vue项目使用websocket做聊天项目总结

    一.首先我们先了解一下websocket的使用: 1.创建websocket const ws = new WebSocket("ws://192.168.31.136:9998/ws&qu ...

  2. maven项目添加websocket

    最近由于项目业务需求,需要用到websocket来实现即时信息的推送,学习了一下websocket,网上搜了一下学习教程,很多版本看的我云里雾里,最后选择用tomcat提供的最新版本(tomcat 启 ...

  3. vue项目使用websocket技术

    一.为什么需要websocket? 前端和后端的交互模式最常见的就是前端发数据请求,从后端拿到数据后展示到页面中.如果前端不做操作,后端不能主动向前端推送数据,这也是http协议的缺陷. 因此,一种新 ...

  4. HTML5学习总结-08 WebSocket 服务器推送

    一 WebSocket 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展 ...

  5. JAVAEE——BOS物流项目08:配置代理对象远程调用crm服务、查看定区中包含的分区、查看定区关联的客户

    1 学习计划 1.定区关联客户 n 完善CRM服务中的客户查询方法 n 在BOS项目中配置代理对象远程调用crm服务 n 调整定区关联客户页面 n 实现定区关联客户 2.查看定区中包含的分区 n 页面 ...

  6. Java web项目使用webSocket

    前端: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&qu ...

  7. Go语言【项目】 websocket消息服务

    websocket消息服务 目的:搭建websocket服务,用浏览器与服务进行消息交互(写的第一个Go程序) 代码目录结构: 前端html页面: <!DOCTYPE html> < ...

  8. 开源项目 08 IOC Autofac

    using Autofac; using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  9. AndroidAsync :异步Socket,http(client+server),websocket和socket.io的Android类库

    AndroidAsync是一个用于Android应用的异步Socket,http(client+server),websocket和socket.io的类库.基于NIO,没有线程.它使用java.ni ...

随机推荐

  1. FFmpeg内存操作(三)内存转码器

    相关博客列表 : FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 FFMPEG内存操作(二)从内存中读取数及数据格式的转换 FFmpeg内存操作(三)内存转码器 本文 ...

  2. H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式(包含AAC部分解析)

    H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +------------ ...

  3. android开发 如何通过web服务器访问MYSQL数据库并且使其数据同步到android SQLite数据库?

    通过web服务器访问MYSQL数据库有以下几个过程: 1.在MySql下创建自己的数据库和自己的表单 2.连接数据库. 3.访问数据库 1.创建web工程 (服务器端) 在Myeclipse下新建一个 ...

  4. Unity实现支持泛型的事件管理以减少使用object作为参数带来的频繁装拆箱

    如果不用C#自身的event关键字而是要自己实现一个可统一管理游戏中各种消息事件通知管理的系统模块EventManger时,通常都是把事件delegate的参数定义为object类型以适应所有的数据类 ...

  5. 8、scala面向对象编程之Trait

    一.Trait基础 1.将trait作为接口使用 // Scala中的Triat是一种特殊的概念 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 // 在t ...

  6. AT指令集

    通用指令 at+cala   设置警报日期和时间 at+cgmi  厂家认证请求,返回模块厂家信 at+cgmm 模式认证请求,返回模块使用频段 at+cgmr 修正认证请求,返回软件版本 at+cg ...

  7. Linux下查看CPU使用率 --- top命令的使用

    在系统维护的过程中,随时可能有需要查看 CPU 使用率,并根据相应信息分析系统状况的需要.在 CentOS 中,可以通过 top 命令来查看 CPU 使用状况.运行 top 命令后,CPU 使用状态会 ...

  8. POJ 3693 Maximum repetition substring (后缀数组+RMQ)

    题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...

  9. javascript 操作符小结

    简单总结一下JavaScript的几个操作符: var. in. delete. typeof. new. instanceof.void var 定义变量要使用var操作符, 使用var操作符定义的 ...

  10. 新安装的 ubuntu 下 make menuconfig 报错

    环境:Ubtuntu 12.04 LTS 新安装的ubuntu 出现不能使用make menuconfig. 1.sudo apt-get update 更新软件 2.安装下面的软件 sudo apt ...