你真的会websocket吗
Websocket
Django用法
在1.9版本之后,Django实现了对Channels的支持,他所使用的是WebSocket通信,解决了实时通信的问题,而且在使用WebSocket进行通信的同时依旧能够支持HTTP通信。
1.1目录结构
在此结构中必须有硬性要求,具体如下:
新的目录如下:
|-- channels_example
| |--channels_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- routing.py #必须
| |-- consumer.py #必须
| |-- asgi.py
| |-- manage.py
1.2配置settings.py文件
1.2.1将其添加到APP列表里
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
]
1.2.2然后,添加新的参数CHANNEL_LAYERS,如下:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "channels_example.routing.channel_routing",
},
}
需要注意的是 ROUTING 参数,他是用来指定WebSocket表单的位置,当有WebSocket请求访问时,就会根据这个路径找到相应表单,调用相应的函数进行处理。
channels_example.routing 就是我们刚才建好的routing,py文件,里面的channel_routing我们下面会进行填充。
1.3填写路由映射地址
from channels.routing import route
import consumers channel_routing = [
route('websocket.connect', consumers.ws_connect),
route('websocket.disconnect', consumers.ws_disconnect),
# route('websocket.receive', consumers.ws_message),
route('websocket.receive', consumers.ws_message_uuid),
]
1.4路由映射到相对应的函数
from django.http import HttpResponse
from channels.handler import AsgiHandler #message.reply_channel 一个客户端通道的对象
#message.reply_channel.send(chunk) 用来唯一返回这个客户端 #一个管道大概会持续30s def ws_connect(message):
auth = True if not auth:
reply = json.dumps({'error': error})
message.reply_channel.send({'text': reply, 'close': True})
else:
reply = "{}"
message.reply_channel.send({'text': reply})
print(">>> %s connected" % str(message)) def ws_disconnect(message):
print("<<< %s disconnected" % str(message))
# with message_queue.mutex:
# message_queue.queue.clear()
while not message_queue.empty():
try:
message_queue.get(False)
except Empty:
continue message_queue.task_done() def ws_message_uuid(message):
task = Task.create(message) if task:
message_queue.put(task)
tornado用法
1.1Tornado的WebSocket模块
Tornado在websocket模块中提供了一个WebSocketHandler类。这个类提供了和已连接的客户端通信的WebSocket事件和方法的钩子。当一个新的WebSocket连接打开时,open方法被调用,而on_message和on_close方法分别在连接接收到新的消息和客户端关闭时被调用。
此外,WebSocketHandler类还提供了write_message方法用于向客户端发送消息,close方法用于关闭连接。
class EchoHandler(tornado.websocket.WebSocketHandler):
def open(self):
self.write_message('connected!') def on_message(self, message):
self.write_message(message)
正如你在我们的EchoHandler实现中所看到的,open方法只是使用WebSocketHandler基类提供的write_message方法向客户端发送字符串"connected!"。每次处理程序从客户端接收到一个新的消息时调用on_message方法,我们的实现中将客户端提供的消息原样返回给客户端。这就是全部!让我们通过一个完整的例子看看实现这个协议是如何简单的吧。
WebSocketHandler.open()
当一个WebSocket连接建立后被调用。
WebSocketHandler.on_message(message)
当客户端发送消息message过来时被调用,注意此方法必须被重写。
WebSocketHandler.on_close()
当WebSocket连接关闭后被调用。
WebSocketHandler.write_message(message, binary=False)
向客户端发送消息messagea,message可以是字符串或字典(字典会被转为json字符串)。若binary为False,则message以utf8编码发送;二进制模式(binary=True)时,可发送任何字节码。
WebSocketHandler.close()
关闭WebSocket连接。
WebSocketHandler.check_origin(origin)
判断源origin,对于符合条件(返回判断结果为True)的请求源origin允许其连接,否则返回403。可以重写此方法来解决WebSocket的跨域请求(如始终return True)。
1.2实例--工作websocket实际应用
#coding=utf-8 import uuid
import os
from works.actions import work
import hashlib
import json
import Queue
from threading import Thread
import numpy as np
import cv2
import base64
import jwt
import tornado.gen
from handlers.base_handler import BaseWebSocket
from config import MEDIA_ROOT
import time message_queue = Queue.PriorityQueue() def work_loop():
while True:
task = message_queue.get() iuuid = task.uuid
offset_top = task.offset_top
image_data = task.image_data
channel = task.channel
zoom = task.zoom
rType = task.rType
responseType = task.responseType print(">>> len: %d | current offset: %d" % (message_queue.qsize(), offset_top)) filename = str(uuid.uuid1()) + '.jpg'
filepath = os.path.join(MEDIA_ROOT, filename) with open(filepath, 'wb') as f:
f.write(image_data.decode("base64")) if zoom != 1.0:
im = cv2.imread(filepath) if im is None:
continue osize = im.shape[1], im.shape[0]
size = int(im.shape[1] * zoom), int(im.shape[0] * zoom)
im = cv2.resize(im, size)
cv2.imwrite(filepath, im) try:
reply = work(filepath, use_crop=False, result=rType,responseType=responseType)
except Exception as e:
print("!!!!!! %s -> %s caused error" % (iuuid, filename))
print(e)
cmd = u"cp %s %s" % (filepath, os.path.join(MEDIA_ROOT, 'rb_' + filename))
os.system(cmd.encode('utf-8'))
continue if responseType == 'url':
# rtn_url = 'http://101.236.17.104:3389/upload/' + 'rb_' + filename
rtn_url = 'http://192.168.0.254:8000/upload/' + 'rb_' + filename
reply = {'url': rtn_url, 'uuid': iuuid} reply['uuid'] = iuuid
channel.write_message({'text': json.dumps(reply)})
print '%s end time:' % channel, time.time() class BrowserWebSocket(BaseWebSocket): '''浏览器websocket服务器''' def open(self):
'''新的WebSocket连接打开时被调用'''
# message = {}
# remote_ip = self.request.remote_ip
# message['query_string']=self.get_argument('query_string')
# message['remote_ip']=remote_ip
# auth, error = verify_auth_token(message)
auth = True
error = 'error' if not auth:
reply = json.dumps({'error': error})
self.write_message({'text': reply, 'close': True})
else:
reply = "{}"
self.write_message({'text': reply})
print(">>> %s connected" % self.request.remote_ip) def on_message(self, message):
'''连接收到新消息时被调用'''
print '%s start time:'%self,time.time()
task = Task.create(message,self) if task:
message_queue.put(task) @tornado.gen.coroutine
def on_messages(self, message):
'''连接收到新消息时被调用'''
task = Task.create(message,self) if task:
message_queue.put(task) def on_close(self):
'''客户端关闭时被调用'''
print("<<< %s disconnected" % str(self.request.remote_ip))
# with message_queue.mutex:
# message_queue.queue.clear()
while not message_queue.empty():
try:
message_queue.get(False)
except Queue.Empty:
continue message_queue.task_done() def check_origin(self, origin):
'''允许WebSocket的跨域请求''' return True class Task(object):
def __init__(self, uuid, offset_top, image_data, channel, zoom, rType, responseType, *args):
self.uuid = uuid
self.offset_top = int(float(offset_top))
self.image_data = image_data
self.channel = channel
self.zoom = zoom
self.rType = rType
self.responseType = responseType @classmethod
def create(clz, message,sel):
# data = message.get('text')
data = message try:
params = json.loads(data[:150]) image_data = data[150:]
image_data = image_data.replace(" ", "+") params['image_data'] = image_data
params['channel'] = sel # add Type
if params.get('responseType') is None:
params['responseType'] = 'url' # request type
if params.get('rType') is None:
params['rType'] = 'rl' task = Task(**params) except ValueError as e:
task = None
print(">>>message data error!")
print(e) return task def __cmp__(self, other):
return cmp(self.offset_top, other.offset_top) def verify_auth_token(message):
'''token 验证''' token = message.get('query_string')
secret_key = 'aoiakai' try:
payload = jwt.decode(token, secret_key, algorithms=['HS256'])
if payload.get('ip') != message.get('remote_ip'):
return False, 'ip mismatch'
except jwt.ExpiredSignatureError as e:
print(e)
return False, 'token expired'
except Exception as e:
print(e)
return False, 'enter correct token' return True, '' work_thread = Thread(target=work_loop)
work_thread.daemon = True
work_thread.start()
你真的会websocket吗的更多相关文章
- 你真的了解WebSocket吗?
WebSocket协议是基于TCP的一种新的协议.WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符.它实现了浏览器与服务器全双工(full-duplex ...
- websocket的介绍
偶然在知乎上看到一篇回帖,瞬间觉得之前看的那么多资料都不及这一篇回帖让我对 websocket 的认识深刻有木有.所以转到我博客里,分享一下.比较喜欢看这种博客,读起来很轻松,不枯燥,没有布道师的阵仗 ...
- WebSocket///////////////////////z
作者:Ovear链接:http://www.zhihu.com/question/20215561/answer/40316953来源:知乎著作权归作者所有,转载请联系作者获得授权. 一.WebSoc ...
- 萌萌的websocket原理解析
转载自:http://www.zhihu.com/question/20215561 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持 ...
- Websocket 概述
WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex). [[ from websocket是什么原理? ]] 一.WebSocke ...
- WebSocket 是什么原理?为什么可以实现持久连接?
https://www.zhihu.com/question/20215561 作者:Ovear链接:https://www.zhihu.com/question/20215561/answer/ ...
- WebSocket原理及与http1.0/1.1 long poll和 ajax轮询的区别【转自知乎】
一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的ke ...
- WebSocket能干啥
------这东西到底有什么用途,仔细看了说明,还是不明所以.楼上几位能不能介绍一下实际使用的场景?? 1.可以实现 服务器端(delphi&lazarus@win)<->手机端 ...
- WebSocket的原理,以及和Http的关系
一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. ...
随机推荐
- MySQL数据库学习四 存储引擎和数据类型
4.1存储引擎 1. 查看MySQL DBMS所支持的存储引擎 SHOW ENGINES;
- poj-3660-cows contest(不懂待定)
Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming con ...
- Spring AOP: 织入的顺序
spring AOP 采用和 AspectJ 一样的优先顺序来织入增强处理:在进入连接点时,高优先级的增强处理将先被织入:在退出连接点时,高优先级的增强处理会后被织入. 当不同的切面里的两个增强处理需 ...
- Webpack 引入bootstrap
Bootstrap中是一种事实上的界面标准,标准到现在的网站大量的使用它.如果可以使用webpack引入的bootstrap.css,就可以一个npm install完成项目的依赖,而不必手工的添加到 ...
- 【Flask】 利用uWSGI和Nginx发布Flask应用
因为Flask比较容易上手,之前也拿flask写过几个小项目,不过当时天真地以为只要在服务器上nohup跑一个python脚本就算是成功发布了这个flask项目.实际上这还面临很多问题,比如并发性不好 ...
- [css 实践篇] 解决悬浮的<header> <footer>遮挡内容的处理技巧
我写的实践篇 都是自己在实践项目所遇到的 "拦路虎" 还是很有借鉴的意义的.(实践才是检验真理的唯一标准呀),废话不多说,进去正题 position: fixed 绝对固定底部后会 ...
- [css 揭秘]:CSS揭秘 技巧(四):边框内圆角
我的github地址:https://github.com/FannieGirl/ifannie/ 源码都在这上面哦! 喜欢的给我一个星吧 边框内圆角 问题:有时候我们需要一个容器,只在内侧有圆角,而 ...
- 如何测试一个WEB的输入框?
WEB输入框是B/S架构系统中页面使用非常频繁的控件,比如我们登录一个网站,输入 用户名和密码的控件都是输入框,比如使用百度搜索,在输入搜索内容的控件也是输入框,比如网购一个物品,我们需要输入购买的数 ...
- 关于使用Unity开发Kinect时出现的Runtime Error错误的解决方式
一.开发环境: 1. 硬件:Kinect 2.0 2. 操作系统:Windows10 3. Unity版本:5.x以上 4. Kinect SDK:KinectSDK-v2.0_1409 5. Kin ...
- JavaScript(第二十一天)【DOM元素尺寸和位置】
学习要点: 1.获取元素CSS大小 2.获取元素实际大小 3.获取元素周边大小 本章,我们主要讨论一下页面中的某一个元素它的各种大小和各种位置的计算方式,以便更好的理解. 一.获取元素CSS大小 ...