WebSocket with Flask

来源:http://www.cnblogs.com/Vito2008/archive/2016/01/06/5104895.html
-Advertisement-
Play Games

轉自:https://blog.shonenada.com/post/websocket-with-flask/WebSocket with FlaskHTML5 以前,HTML 還不支持WebSocket,當時如果要進行實時的內容更新,要麼使用Ajax輪詢(Polling)或者使用Comet技術。...


轉自:https://blog.shonenada.com/post/websocket-with-flask/

WebSocket with Flask

HTML5 以前,HTML 還不支持 WebSocket ,當時如果要進行實時的內容更新,要麼使用 Ajax輪詢(Polling)或者使用 Comet 技術。

Non-Websocket

Ajax 輪詢

在 2005 年, Jesse James Garrett 提出 Ajax (Asynchronous JavaScript and XML, 非同步 Javascript 和 XML)。具體請看Ajax: A New Approach to Web Applications 。並且從那時開始流行使用 Ajax 進行非同步處理客戶端請求。【關於非同步處理請求的歷史,可以看 http://en.wikipedia.org/wiki/Ajax_(programming) 中相關的介紹】。 XMLHttpRequest 在後臺對伺服器發起 request ,當收到 response 的時候,進行 DOM 操作,從而達到部分更新頁面內容的目的(而不需要整個頁面刷新)。

Ajax 輪詢 可以做到接近實時的更新內容,但是因為是由客戶端發起請求,即伺服器處於被動的狀態,這種“實時”存在缺陷: (1) 偽實時。伺服器有更新的時候,只有客戶端發起請求,伺服器才能將更新返回到客戶端。 (2) 數據更新量少的時候,容易造成浪費帶寬、流量。 (3) 請求頻率難以把握。太快會對伺服器造成過大的壓力,而太慢又不夠“實時”,權衡頻率需要考慮的因素很多。

Comet 技術

Comet 是指不需要客戶端瀏覽器安裝任何插件,僅靠瀏覽器和伺服器之間的長 HTTP 連接實現伺服器向客戶端通信(伺服器推)的技術。 Comet 有兩種方式: Ajax長輪詢 和 iframe with htmlfile stream

iframe with htmlfile streaming

這種技術,暫時沒使用過。基本原理是使用 iframe 標簽在 html 中插入一個隱藏的幀,向伺服器建立長連接,伺服器不斷地向 iframe 輸入數據。

Ajax 長輪詢

Ajax 長輪詢本質上也是 Ajax 輪詢,不同的是,在伺服器端做了些修改。當伺服器沒有更新的時候,伺服器將請求阻塞,直到 有更新 或 連接超時。當請求結束之後再進行第二次的請求。

這種方式基本上可以避開 Ajax 輪詢的缺陷。 Tornado 框架中的 Asynchronous 功能就是通過阻塞請求實現非同步更新。 通過 Tornado 框架提供的 Asynchronous 功能可以實現實時數據傳遞。歡迎參考我在學習使用 tornado 非同步功能時實現的兩段應用:

  1. https://github.com/shonenada/chat-in-command-line
  2. https://github.com/shonenada/guess-number // 這程式功能不完善,但實現了非同步的功能。

WebSocket

WebSocket 是 HTML5 的新功能,它是一種 TCP 協議。當客戶端和伺服器完成握手,建立連接之後,ws 就如普通 socket 一樣,在兩者之間進行通信。

理解了基本通信原理,就可以進行編程了。

前面已說,WS 是一種 TCP 協議,所以是語言無關的,用任何語言都可以實現伺服器端的編程。我選擇了 Python,使用 _flask: http://flask.pocoo.org/ 作為框架,以 _Gevent: http://www.gevent.org/ 和 _gevent-websocket:https://pypi.python.org/pypi/gevent-websocket/ 做 HttpServer。

實時更新基本的實現思路:

  1. 客戶端發起 ws 連接請求
  2. 伺服器響應,並且把 ws 加入到 observer 數組中。
  3. 當某一 ws 向伺服器發送信息時,伺服器遍歷 observers 數組向每一個元素髮送信息。
  4. ws 斷開連接時,從 observer 中剔除。

具體實現代碼:

# manage.py
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from flask import Flask, request, render_template, abort

import message


msgsrv = message.MessageServer()

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('message.html')


@app.route('/message/')
def message():
    if request.environ.get('wsgi.websocket'):
        ws = request.environ['wsgi.websocket']
        msgsrv.observers.append(ws)
        while True:
            if ws.socket:
                message = ws.receive()
                if message:
                    msgsrv.add_message("%s" % message)
            else:
                abort(404)
    return "Connected!"


if __name__ == '__main__':
    http_server = WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
    http_server.serve_forever()
# message.py
from geventwebsocket import WebSocketError


class MessageServer(object):

    def __init__(self):
        self.observers = []

    def add_message(self, msg):
        for ws in self.observers:
            try:
                ws.send(msg)
            except WebSocketError:
                self.observers.pop(self.observers.index(ws))
                print ws, 'is closed'
                continue
<!-- templates/message.html -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta http-equiv="Content-Language" content="zh-CN"/>
        <title>實時消息</title>
        <link rel="stylesheet" href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css">
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" charset="utf-8">
        $(document).ready(function(){
            $('form').submit(function(event){
                ws.send($(this).serialize());
                return false;
            });
            if ("WebSocket" in window) {
                ws = new WebSocket("ws://" + document.domain + ":5000/message/");
                ws.onmessage = function (msg) {
                    console.log(msg.data);
                };
            } else {
                alert("WebSocket not supported");
            }
            window.onbeforeunload = function() {
                ws.onclose = function () {
                    console.log('unlodad')
                };
                ws.close()
            };
        });
        </script>
    </head>
    <body>
        <div class="header container">
            <h1>實時消息</h1>
            <ul class="tabs">
                <li class="active">
                    <a href="/">DEMO</a>
                </li>
            </ul>
        </div>
        <div class="container">
            Pls check your Chrome console.
            <form class="row" id="message_form">
                <div class="span10">
                    <div class="clearfix">
                        <label for="chat_content">消息</label>
                        <div class="input">
                            <textarea id="chat_content" name="content" class="xlarge" rows="6"></textarea>
                        </div>
                    </div>
                    <div class="well align-center">
                        <input type="submit" class="btn primary" value="發佈">
                        &nbsp;
                        <input type="reset" class="btn" value="清空">
                    </div>
                </div>
            </form>
        </div>
        <div class="footer container">
            <p>
                &copy; Copyright by shonenada
            </p>
        </div>
    </body>
</html>

~接下來可以實現 HTML5 的桌面直播了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • jQuery列印json格式對象實例代碼:所謂的json格式對象其實就是對象直接量,很多教程多說這是json對象,其實這是不正確。下麵是一段列印json格式對象的實例代碼,希望能夠對初學者有所幫助。代碼如下: 螞蟻部落 原文地址是:http://www.softwhy.com/f...
  • 通過上下左右鍵控制div的運行方向:使用小鍵盤附近的上下左右鍵控制方向可能在很多應用程式中都有用到,有時候甚至特別的方便,比如有些游戲可以使用者四個鍵控制方位,下麵就簡單介紹一下javascript如何實現使用這四個鍵控制div的運動方向。方向鍵控制div的移動-螞蟻部落紅色方塊為鍵盤操作區域,您可...
  • 實現table細線表格效果代碼:細線表格相比較表格的預設表格來說要美觀很多,當然更受歡迎,下麵就通過代碼實例介紹一下如何實現此效果。代碼如下: 螞蟻部落 螞蟻部落一 螞蟻部落二 javascript教程 jQuery教程 ...
  • jQuery實現的垂直可伸縮導航菜單:垂直可伸縮導航菜單在網頁中非常的常用,首先可以進行分類,第二個也可以節省網頁的空間,本章節就通過實例代碼分享一個這樣的效果,希望能夠給需要者帶來一定的幫助。代碼實例如下:螞蟻部落 螞蟻部落一 前端教程 ...
  • javascript實現的iframe數據共用介面:在iframe與父視窗或者與子視窗傳遞數據是一個麻煩的事情,如果我們能夠寫一個一勞永逸的介面那就再方便不過了,下麵就來簡答介紹一下如何實現此功能。原理就是將數據緩存早window.top這個視窗,這樣無論子視窗父視窗的層次如何變化,數據總是存在不會...
  • 查看效果:http://hovertree.com/texiao/css/14/本效果用css3的animation實現動畫定義和用法animation 屬性是一個簡寫屬性,用於設置六個動畫屬性:animation-nameanimation-durationanimation-timing-fun...
  • Dubbo服務的運行方式 服務容器是一個standalone的啟動程式,因為後臺服務不需要Tomcat或JBoss等Web容器的功能,如果硬要用Web容器去載入服務提供方,增加複雜性,也浪費資源。 服務容器只是一個簡單的Main方法,並載入一個簡單的Spring容器,用於暴露服務。 服務容器的載入內...
  • /*目的:創建一個單鏈表,實現尾部插入,頭部插入,遍歷鏈表*/#include #include #include //定義一個結構體,用來表示一個節點,包含指針域,數據域struct node{ int data; //數據域 struct node *next; //指針域,...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...