菜单

澳门金沙国际Tornado 四.三文书档案翻译: web框架-websocket浏览器与服务器双向通讯

2019年4月10日 - 金沙编程资讯

示例2:

闭馆连接

客户端要积极关闭连接,在JS中调用 socket.close()
即可,此时出殡的多少包为
41,在那之中四意味的是engine.io的消息类型message,而数据1则是指的socket.io的音信类型disconnect,关闭流程见上一章的注脚。

class tornado.websocket.WebSocketClientConnection(io_loop, request, on_message_callback=None, compression_options=None)

WebSocket 客户端连接

其1类不应有直接被实例化, 请使用 websocket_connect

HTML代码:python3知识点

微信QQ

#chatcontent{

/*来得内容使用的*/

width:500px;

height:200px;

background-color:pink;

overflow-y:scroll;

overflow-x:scroll;

}

发送

ws=newWebSocket(‘ws://192.168.1.27:8009/chat’)

//服务器给浏览器推送新闻的时候回调

ws.onmessage=function(p1) {

$(‘#chatcontent’).append(‘

‘+p1.data+’

‘)

}

functionsend() {

varcontent=$(‘#msg_container’).val()

ws.send(content)

$(‘#msg_container’).val(”)

}

ping_timeout:假诺未有收到pong新闻,则为超时(秒)。

服务端发送新闻到客户端

服务端发送音信通过
flask_socketio提供的emit方法达成,如前壹节分析的,最后照旧经过的engine.io包装成engine.io的音信格式后产生。

42["server_response",{"data":"TEST"}]

Output

web服务器代码:

#coding=utf-8

importtornado.websocket

importtornado.web

importtornado.ioloop

importdatetime

classIndexHandler(tornado.web.RequestHandler):

defget(self, *args, **kwargs):

self.render(‘templates/index.html’)

classWebHandler(tornado.websocket.WebSocketHandler):

users =set()#存放在线用户

defopen(self, *args, **kwargs):

self.users.add(self)#把建立连接后的用户拉长到用户容器中

foruserinself.users:#向在线的用户发送进入消息

user.write_message(“[%s]-[%s]-进入聊天室”%
(self.request.remote_ip,

datetime.datetime.now().strftime(“%Y-%m-%d %H:%M:%S”)))

defon_close(self):

self.users.remove(self)# 用户关闭连接后从容器中移除用户

foruserinself.users:

user.write_message(“[%s]-[%s]-离开聊天室”%
(self.request.remote_ip,

datetime.datetime.now().strftime(“%Y-%m-%d %H:%M:%S”)))

defon_message(self, message):

foruserinself.users:#向在线用户发送聊天音讯

user.write_message(“[%s]-[%s]-说:%s”% (self.request.remote_ip,

datetime.datetime.now().strftime(“%Y-%m-%d %H:%M:%S”), message))

defcheck_origin(self, origin):

return True# 允许WebSocket的跨域请求

importos

BASE_DIR = os.path.dirname(__file__)

settings = {

‘static_path’:os.path.join(BASE_DIR,’static’),

“websocket_ping_interval”:1,

“websocket_ping_timeout”:10

}

app = tornado.web.Application([(r’/’,IndexHandler),

(r’/chat’,WebHandler)],

**settings)

app.listen(8009)

tornado.ioloop.IOLoop.instance().start()


(4)on_message:这些目的在吸收接纳到服务器再次回到的音信时调用。有七个参数,1个是此类本身,二个是大家从服务器获取的字符串(utf-八格式)。

服务端接收新闻流程

而服务端接收音讯并赶回多少个新的event为”server_response”,数据为”TEST”,代码如下,此中socketio是flask_socketio模块的SocketIO对象,它提供了装饰器方法
on将自定义的client_event和拍卖函数test_client_event注册到sockerio服务器的handlers中。

当接受到 client_event 消息时,会通过sockerio/server.py中的
_handle_eio_message()方法处理音信,对于socket.io的EVENT类型的音信最后会因而_trigger_event()措施处理,该措施也正是从handlers中获得client_event对应的处理函数并调用之。

from flask_socketio import SocketIO, emit
socketio = SocketIO(...)

@socketio.on("client_event")
def test_client_event(msg):
    emit("server_response", {"data": msg["data"].upper()})

class tornado.websocket.WebSocketHandler(application, request, **kwargs)

透过一而再该类来成立1个核心的 WebSocket handler.

重写 on_message 来处理收到的音信, 使用 write_message
来发送消息到客户端. 你也足以重写 open 和 on_close
来处理连接打开和关闭那多个动作.

有关JavaScript 接口的详细音信:
http://dev.w3.org/html5/websockets/
具体的合计:
http://tools.ietf.org/html/rfc6455

多个简练的 WebSocket handler 的实例:
服务端间接回到全体接受的新闻给客户端

class EchoWebSocket(tornado.websocket.WebSocketHandler):
    def open(self):
        print("WebSocket opened")

    def on_message(self, message):
        self.write_message(u"You said: " + message)

    def on_close(self):
        print("WebSocket closed")

WebSockets 并不是专业的 HTTP 连接. “握手”动作符合 HTTP
标准,不过在”握手”动作之后, 协议是基于新闻的. 由此,Tornado 里多数的
HTTP 工具对于那类 handler 都是不可用的. 用来广播发表的点子唯有write_message() , ping() , 和 close() . 同样的,你的 request handler
类里应该运用 open() 而不是 get() 也许 post()

设若你在动用上校以此 handler 分配到 /websocket, 你能够因而如下代码达成:

var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onopen = function() {
   ws.send("Hello, world");
};
ws.onmessage = function (evt) {
   alert(evt.data);
};

以此剧本将会弹出二个提醒框 :”You said: Hello, world”

浏览器并从未遵照同源策略(same-origin policy),相应的允许了自由站点使用
javascript 发起任意 WebSocket
连接来控制别的网络.这让人诧异,并且是八个潜在的安全漏洞,所以 从 Tornado
四.0 开端 WebSocketHandler 须要对希望接受跨域请求的运用通过重写.

check_origin (详细新闻请查看文书档案中关于该措施的有的)来展开设置.
未有科学配置这么些特性,在确立 WebSocket 连接时候很大概会导致 40三 错误.

当使用安全的 websocket 连接(wss://) 时, 来自浏览器的连接恐怕会破产,因为
websocket 未有位置输出 “认证成功” 的对话. 你在 websocket
连接建立成功此前,必须 使用同样的注解访问二个好端端的 HTML 页面.

python3知识点

jquery.min.js

澳门金沙国际 1

(10)get_mask_key:用于产生贰个掩码。

关闭连接(只分析websocket)

websocket恐怕尤其关闭的情状多多。比如客户端发了ping后等候pong超时关闭,服务端接收到ping跟上叁个ping之间超过了pingTimeout;用的uwsgi的话,uwsgi发送ping,假诺在websockets-pong-tolerance(暗中同意3秒)内接受不到pong回应,也会关闭连接;还有如若nginx的proxy_read_timeout配置的比pingInterval小等。

假定不是客户端主动关闭连接,socket.io就会在连年出错后连连重试以树立连接。重试间隔和重试次数由reconnectionDelayMax(默认5秒)reconnectionAttempts(暗中同意平昔重连)设定。下边研商客户端平常关闭的情状,各样相当关闭状态请具体情状具体分析。

客户端主动关闭

假诺客户端调用socket.close()百尺竿头更进一步关闭websocket连接,则会首发送四个音信41(肆:engine.io的message,一:socket.io的disconnect)再关闭连接。如前方提到,engine.io套接字接收到音讯后会交给socket.io服务器注册的
_handle_eio_message()处理。最终是调用的socket.io的_handle_disconnect(),该函数工作包括调用socketio.on("disconnect")挂号的函数,将该客户端从加入的屋子中移除,清理环境变量等。

uwsgi而接受到客户端关闭websocket连接音信后会关闭服务端到客户端的连天。engine.io服务器的websocket数据接受例程ws.wait()因为老是关闭报IOError,触发服务端循环收发数据经过甘休,并从爱护的sockets集合中移除那一个闭馆的sid。然后调用engine.io套接字的close(wait=True, abort=True)措施,由于是客户端主动关闭,那里就不会再给客户端发送七个CLOSE音信。而
engine.io服务器的close方法同样会触发socket.io在此以前注册的disconnect事件处理函数,由于后面早已调用_handle_disconnect()拍卖了关闭连接事件,所以那边_handle_eio_disconnect()不必要再做别的操作(这几个操作不是剩下的,其作用见后壹节)。

浏览器关闭

平素关门浏览器发送的是websocket的标准CLOSE音讯,opcode为八。socket.io服务端处理情势基本一致,由于那种情状下并未发送socket.io的关门新闻41,socket.io的倒闭操作须要等到engine.io触发的_handle_eio_disconnect()中处理,那便是前1节中为啥engine.io服务器前面还要多调用一回
_handle_eio_disconnect()的因由所在。

tornado.websocket — 浏览器与服务器双向通讯

WebSocket 协议的落到实处

WebSockets 允许浏览器和服务器之间举行 双向通讯

全数主流浏览器的当代版本都支持WebSockets(补助情状详见:http://caniuse.com/websockets)

该模块遵照最新 WebSocket 协议 LX570FC 645伍 达成.

在 4.0 版更改: Removed support for the draft 76 protocol version.

ws.run_forever(ping_interval=60,ping_timeout=5)

#ping_interval心跳发送间隔时间

#ping_timeout 设置,发送ping到收到pong的超时时间

总是建立

先是,客户端会发送三个polling请求来建立连接。此时的央求参数未有sid,表示要成立连接。
engine.io服务器通过handle_get_request()handle_post_request()艺术来分别处理起初化连接以及长轮询中的
GET 和 POST 请求。

socket.io在开始化时便登记了二个事件到engine.io的handlers中,分别是connect(处理函数_handle_eio_connect),message(_handle_eio_message),disconnect(_handle_eio_disconnect),在engine.io套接字接收到了上述多少个类其他音信后,在自家做了对应处理后都会触发socket.io中的对应的处理函数做进一步处理。

当收到到GET请求且未有sid参数时,则engine.io服务器会调用
_handle_connect()艺术来树立连接。这几个点子主要办事是为当下客户端生成sid,成立Socket对象并保存到engine.io服务器的sockets集合中。做了那个起始化工作后,engine.io服务器会发送二个OPEN类型的数量包给客户端,接着会触发socket.io服务器的connect事件。

客户端第三回连续的时候,socket.io也要做壹些起始化的行事,那是在socket.io服务器的_handle_eio_connect()处理的。那里做的业务根本有几点:

最后在响应中engine.io会为客户端设置一个名称为io值为sid的cookie,响应内容payload蕴涵八个数据包,2个是engine.io的OPEN数据包,内容为sid,pingTimeout等配备和参数;另2个是socket.io的connect数据包,内容为40。在那之中肆意味的是engine.io的message音讯,0则表示socket.io的connect音讯,以字节流回到。那里的pingTimeout客户端和服务端共享这些布局,用于检验对端是或不是过期。

接着会发送一个轮询请求和websocket握手请求,要是websocket握手成功后客户端会发送2 probe探测帧,服务端回应3 probe,然后客户端会发送内容为5的Upgrade帧,服务端回应内容为6的noop帧。探测帧检查通过后,客户端截止轮询请求,将传输通道转到websocket连接,转到websocket后,接下去就从头为期(暗许是二5秒)的
ping/pong(那是socket.io自定义的ping/pong,除却,uwsgi也会定期(暗中认可30秒)对客户端ping,客户端回应pong,那几个在chrome的Frames里面是看不到的,要求重视wireshark恐怕用任何浏览器插件来察看)。

Other

    ws = websocket.WebSocketApp("ws://echo.websocket.org/",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()

2 WebSocket协议

我们了然,在HTTP 协议开发的时候,并不是为着双向通讯程序准备的,起首的
web 应用程序只要求 “请求-响应”
就够了。由于历史原因,在制造拥有双向通讯机制的 web
应用程序时,就不得不动用 HTTP 轮询的法门,由此发生了 “短轮询” 和
“长轮询”(注意区分短连接和长连接)。

短轮询通过客户端定期轮询来打探服务端是不是有新的新闻发出,缺点也是显眼,轮询间隔大了则音讯不够实时,轮询间隔过小又会消耗过多的流量,扩大服务器的承受。长轮询是对短轮询的优化,必要服务端做相应的改动来支持。客户端向服务端发送请求时,假使此刻服务端没有新的新闻发出,并不立时回去,而是Hang住一段时间等有新的新闻依旧逾期再回来,客户端收到服务器的答复后持续轮询。能够看到长轮询比短轮询能够收缩大气空头的乞请,并且客户端接收取新音讯也会实时不少。

虽说长轮询比短轮询优化了许多,不过每回请求还是都要带上HTTP请求尾部,而且在长轮询的三番五次完结今后,服务器端积累的新消息要等到下次客户端连接时才能传递。更加好的艺术是只用八个TCP连接来达成客户端和服务端的双向通讯,WebSocket磋商正是为此而生。WebSocket是基于TCP的3个独立的商业事务,它与HTTP协议的绝无仅有涉嫌就是它的拉手请求能够用作二个Upgrade request行经HTTP服务器解析,且与HTTP使用同样的端口。WebSocket暗许对壹般性请求使用80端口,协议为ws://,对TLS加密请求使用4四三端口,协议为wss://

握手是由此二个HTTP Upgrade request千帆竞发的,一个伸手和响应底部示例如下(去掉了毫不相关的尾部)。WebSocket握手请求尾部与HTTP请求尾部是合作的(见LacrosseFC261陆)。

## Request Headers ##
Connection: Upgrade
Host: socket.io.demo.com
Origin: http://socket.io.demo.com
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: mupA9l2rXciZKoMNQ9LphA==
Sec-WebSocket-Version: 13
Upgrade: websocket

## Response Headers ##
101 Web Socket Protocol Handshake
Connection: upgrade
Sec-WebSocket-Accept: s4VAqh7eedG0a11ziQlwTzJUY3s=
Sec-WebSocket-Origin: http://socket.io.demo.com
Server: nginx/1.6.2
Upgrade: WebSocket

WebSocket协商使用帧(Frame)收发数据,帧格式如下。基于平安考量,客户端发送给服务端的帧必须通过④字节的掩码(Masking-key)加密,服务端收到音讯后,用掩码对数据帧的Payload
Data进行异或运算解码获得数码(详见uwsgi的 core/websockets.c
中的uwsgi_websockets_parse函数),假使服务端收到未经掩码加密的数据帧,则应当立时关闭该WebSocket。而服务端发给客户端的数码则不供给掩码加密,客户端假如接收了服务端的掩码加密的数量,则也亟须关闭它。

 0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     +---------------------------------------------------------------+

帧分为控制帧和数据帧,控制帧不能够分片,数据帧可以分片。主要字段表明如下:

close(code=None, reason=None)

关闭 websocket 连接

code 和 reason 的文书档案在 WebSocketHandler.close 下已给出.

③.2 新版功能.

在 四.0 版更改: 添加 code 和 reason 那五个参数

 

四 源码分析

在确立连接后,种种socket会被自动进入到2个默许的命名空间/。在每一个命名空间中,socket会被暗中认可参与多个名称叫Nonesid的屋子。None的屋子用于广播,而sid是时下客户端的session
id,用于单播。除默许的屋子外,我们得以依照须求将对应socket参加自定义房间,roomid唯1即可。socket.io基于engine.io,援助websocket和long
polling。要是是long polling,会定时发送GET,
POST请求,当未有数据时,GET请求在拉取队列信息时会hang住(超时时间为pingTimeout),借使hang住中间服务器平素尚未多少产生,则需求等到客户端发送下一个POST请求时,此时服务器会往队列中贮存POST请求中的音讯,那样上二个GET请求才会回到。假若upgrade到了websocket连接,则会定期ping/pong来保活连接。

为方便描述,下边提到的engine.io服务器对应源文件是engineio/server.py,engine.io套接字对应源文件engineio/socket.py,而socket.io服务器则附和socketio/server.py。上边分析下socket.io连接建立、音讯接收和发送、连接关闭进程。socket.io版本为一.九.0,engine.io版本为二.0.4。

WebSocketHandler.open(*args, **kwargs)

当打开二个新的 WebSocket 时调用

open 的参数是从 tornado.web.ULacrosseLSpec 通过正则表明式获取的, 就像是获取
tornado.web.RequestHandler.get 的参数壹样

 

1 概述

socket.io是二个依照WebSocket的CS的实时通讯库,它底层基于engine.io。engine.io使用WebSocket和xhr-polling(或jsonp)封装了一套本人的商业事务,在不协理WebSocket的低版本浏览器中(支持websocket的浏览器版本见这里)使用了长轮询(long
polling)来取代。socket.io在engine.io的基础上平添了namespace,room,自动重连等特点。

正文接下去会先简单介绍websocket协议,然后在此基础上教学下engine.io和socket.io协议以及源码分析,后续再经过例子表明socket.io的办事流程。

WebSocketHandler.get_compression_options()

重写该措施再次来到当前连年的 compression 选项

设若这些点子再次来到 None (暗中认可), compression 将会被禁止使用. 假若它回到 dict
(固然 是空的),compression 都会被开启. dict 的情节将会被用来控制
compression 所 使用的内部存款和储蓄器和CPU.但是这类的安装现在还平素不被完成.

肆.1 新版作用.

(5)on_error:那个指标在碰到错误时调用,有多个参数,第3个是此类本人,首个是这三个对象。

服务端音信发送流程

而服务端要给客户端发送音讯,则须要通过socket.io服务器的emit方法,注意emit方法是针对room来发送音讯的,假诺是context-aware的,则emit暗许是对namespace为/且room名称叫sid的屋子发送,假若是context-free的,则暗中同意是广播即对富有连接的客户端发送音信(当然在context-free的景色上面,你也能够钦命room来只给钦点room推送信息)。

socket.io要达成多进度以及广播,房间等成效,势必要求衔接贰个redis之类的消息队列,进而socket.io的emit会调用对应队列管理器pubsub_manager的emit方法,比如用redis做新闻队列则最后调用
redis_manager中的_publish()
方法通过redis的订阅公布功用将消息推送到flask_socketio频道。另一方面,全体的socket在连接时都订阅了
flask_socketio频道,而且都有叁个体协会程(或线程)在监听频道中是还是不是有新闻,一旦有音信,就会调用pubsub_manager._handle_emit()办法对本机对应的socket发送对应的新闻,最后是透过socket.io服务器的_emit_internal()情势完毕对本机中room为sid的具备socket发送音讯的,假如room为None,则就是广播,即对具有连接到本机的有所客户端推送新闻。

socket.io服务器发送新闻要基于engine.io音讯包装,所以归纳到底照旧调用的engine.io套接字中的send()艺术。engine.io为各种客户端都会维护二个音讯队列,发送数据都以先存到行列之中待拉取,websocket除了探测帧之外的其它数据帧也都是由此该新闻队列发送。

WebSocketHandler.on_pong(data)

当接到ping 包的响应时执行.

 

客户端发送音讯给服务端

比方要发送新闻给服务器,在浏览器输入框输入test,点击echo按钮,能够看来websocket发送的帧的剧情如下,当中肆是engine.io的message类型标识,二是socket.io的EVENT类型标识,而背后则是事件名称和数码,数据能够是字符串,字典,列表等品种。

42["client_event",{"data":"test"}]

Client-side support

import websocket
from threading import Thread
import time
import sys


class MyApp(websocket.WebSocketApp):
    def on_message(self, message):
        print(message)

    def on_error(self, error):
        print(error)

    def on_close(self):
        print("### closed ###")

    def on_open(self):
        def run(*args):
            for i in range(3):
                # send the message, then wait
                # so thread doesn't exit and socket
                # isn't closed
                self.send("Hello %d" % i)
                time.sleep(1)

            time.sleep(1)
            self.close()
            print("Thread terminating...")

        Thread(target=run).start()


if __name__ == "__main__":
    websocket.enableTrace(True)
    if len(sys.argv) < 2:
        host = "ws://echo.websocket.org/"
    else:
        host = sys.argv[1]
    ws = MyApp(host)
    ws.run_forever()

参考资料

WebSocketHandler.on_close()

当关闭该 WebSocket 时调用

当连接被彻底关闭并且帮忙 status code 或 reason phtase 的时候, 能够透过
self.close_code 和 self.close_reason 那三个个性来赢得它们

在 4.0 版更改: Added close_code and close_reason attributes. 添加
close_code 和 close_reason 这三个个性

pip install websocket-client

3 engine.io和socket.io

前方提到socket.io是基于engine.io的卷入,engine.io(协议版本叁)有1套本身的商谈,任何engine.io服务器都无法不帮助polling(包罗jsonp和xhr)和websocket二种传输情势。engine.io使用websocket时有壹套自身的ping/pong机制,使用的是opcode为0x一(Text)类型的数据帧,不是websocket商谈规定的ping/pong类型的帧,标准的
ping/pong 帧被uwsgi使用

engine.io的数据编码分为Packet和Payload,其中 Packet是数据包,有陆种档次:

而Payload是指一雨后冬笋绑定到1块儿的编码后的Packet,它只用在poll中,websocket里面使用websocket帧里面包车型地铁Payload字段来传输数据。借使客户端不帮忙XHTiguan二,则payload格式如下,当中length是数量包Packet的长短,而packet则是编码后的多寡包内容。

<length1>:<packet1>[<length2>:<packet2>[...]]

若接济XHLX570贰,则payload中情节全方位以贰进制编码,其中第3位0表示字符串,一象征贰进制数据,而背后随着的数字则是代表packet长度,然后以\xff结尾。假使一个长短为十九的字符类型的数据包,则前边长度编码是
\x00\x01\x00\x09\xff,然后前面接packet内容。

<0 for string data, 1 for binary data><Any number of numbers between 0 and 9><The number 255><packet1 (first type,
then data)>[...]

engine.io服务器维护了2个socket的字典结构用于管理总是到该机的客户端,而客户端的标识正是sid。借使有多少个worker,则要求保险同3个客户端的接连落在1如既往台worker上(能够安顿nginx依照sid分发)。因为各种worker只保护了1有个别客户端连接,借使要援助广播,room等个性,则后端须求运用
redis 恐怕 RabbitMQ
新闻队列,使用redis的话则是透过redis的订阅发表机制完成多机多worker之间的音信推送。

socket.io是engine.io的包装,在其基础上平添了自行重连,多路复用,namespace,room等特点。socket.io自个儿也有一套协议,它Packet类型分为(CONNECT 0, DISCONNECT 1, EVENT 2, ACK 3, ERROR 4, BINARY_EVENT 5, BINARY_ACK 6)。注意与engine.io的Packet类型有所不一样,不过socket.io的packet实际是依靠的engine.io的Message类型发送的,在背后实例中得以见见Packet的编码形式。当连接出错的时候,socket.io会通过活动重连机制再次连接。

WebSocketHandler.close(code=None, reason=None)

闭馆当前 WebSocket

假诺挥手动作成功,socket将会被关闭.

code 大概是3个数字构成的状态码, 接纳 冠道FC 645伍 section 7.四.一. 概念的值.

reason 或许是讲述连接关闭的文本音讯. 这几个值被提给客户端,不过不会被
WebSocket 协议单独解释.

在 4.0 版更改: Added the code and reason arguments.

 

5 实例

商业事务表明简单令人多少头晕,websocket,engine.io,socket.io,各自行车运动协会议是怎样工作的,看看实例只怕会相比明晰,为了便于测试,作者写了个Dockerfile,安装了docker的童鞋能够拉取代码执行
bin/start.sh 即可运营拥有完全的
nginx+uwsgi+gevent+flask_socketio测试环境的器皿起头测试,浏览器打开http://127.0.0.1即可测试。async_mode用的是gevent_uwsgi,完整代码见
这里。

对此不帮助websocket的低版本浏览器,socket.io会退化为长轮询的章程,通过定期的发送GET,
POST请求来拉取数据。未有数量时,会将请求数据的GET请求hang住,直到服务端有数据爆发大概客户端的POST请求将GET请求释放,释放之后会跟着再次发送四个GET请求,除却,协议分析和拍卖流程与websocket情势基本壹致。实例只针对使用websocket的进展分析

为了调查socket.io客户端的调用流程,能够设置localStorage.debug = '*';,测试的前段代码片段如下(完整代码见仓库):

 <script type="text/javascript" charset="utf-8">
    var socket = io.connect('/', {
        "reconnectionDelayMax": 10000,
        "reconnectionAttempts": 10
    });
    socket.on('connect', function() {
        $('#log').append('<br>' + $('<div/>').text('connected').html());
    })

    $(document).ready(function() {

        socket.on('server_response', function(msg) {
            $('#log').append('<br>' + $('<div/>').text('Received from server: ' + ': ' + msg.data).html());
        });

        $('form#emit').submit(function(event) {
            socket.emit('client_event', {data: $('#emit_data').val()});
            return false;
        });
    });

 </script>

测试代码比较不难,引进socket.io的js库文件,然后在接连成功后在页面显示“connected”,在输入框输入文字,能够通过连接发送至服务器,然后服务器将浏览器发送的字符串加上server标识回显回来。

PS:本节最佳间接在https://tornado-zh.readthedocs.org或者http://tornado.moelove.info/开卷,以获得更加好的翻阅体验(格式帮助)。原谅本人没排好版QAQ

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图