2014-05-10 19 views
7

Tôi đang cố tạo một máy chủ Flask để truyền dữ liệu đến máy khách bằng sse. Các đoạn mã thử nghiệm dưới đây dường như làm các trick, nhưng tôi stumbled khi một vấn đề liên quan đến xử lý khách hàng ngắt kết nối.Flask sse-stream không kết thúc sau khi ngắt kết nối firefox

Khi sử dụng Firefox làm ứng dụng khách (phiên bản 28 hoặc 29), dữ liệu sẽ bắt đầu phát trực tuyến như mong đợi. Tuy nhiên, khi tôi tải lại trang, luồng mới sẽ được mở (như mong đợi) nhưng luồng cũ vẫn còn. Chuỗi eventgen() xử lý luồng không bao giờ bị chấm dứt. Trên các ứng dụng khách khác (tôi đã thử IE bằng cách sử dụng triển khai Sự kiện Polyfill EventSource của Yaffle cũng như Chrome), tải lại hoặc đóng kết quả trang trong ngắt kết nối của khách hàng, dẫn đến lỗi ổ cắm phía máy chủ 10053 (máy khách bị ngắt kết nối khỏi máy chủ). Điều này chấm dứt vòng lặp và chỉ giữ cho các luồng đang hoạt động còn sống, đó là hành vi mong đợi.

Sử dụng Process Explorer, tôi nhận thấy kết nối TCP ở phía máy khách (Firefox) bị treo trong trạng thái FIN_WAIT2, trong khi kết nối ở phía máy chủ bị treo trong trạng thái CLOSE_WAIT. Điều kỳ lạ là trên 1 trong số 3 máy (tất cả Win 7 x64) chạy Firefox tôi đã thử nghiệm điều này, ngắt kết nối đã được xử lý một cách chính xác. Chạy trên Python 2.6.5 và 2.7.6 tạo ra kết quả tương tự.

Tôi cũng đã thử thay thế máy chủ Flask tích hợp bằng WSGIserver dựa trên greenlet, nhưng điều này dẫn đến chính xác hành vi tương tự. Hơn nữa, một số dạng luồng/sự kiện nên được sử dụng vì nếu không chạy vòng lặp eventgen() sẽ chặn máy chủ.

Mã thử nghiệm bên dưới phục vụ trang được xác định trong make_html() khi duyệt đến máy chủ cục bộ: 5000 và mở luồng đến/luồng. Luồng hiển thị các hình thức massage có dạng {"content": 0,5556278827744346, "local_id": 4, "msg": 6}, trong đó local_id là id của luồng được mở và msg là số của thông báo hiện tại trong luồng này.

import time, random 
import flask 
from flask import Flask, json 

def make_html(): 
    return """ 
     <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script> 
     <script type=text/javascript> 
      var source = new EventSource('/stream'); 
      source.onmessage = function (event) { 
       var data = event.data;     
       var logdiv = $('#log'); 
       logdiv.empty(); 
       logdiv.append('<div class="event">' + data + '</div>'); 
      }; 
     </script> 
     <h1>Log</h1> 
     <div id=log>Log ...</div> 
     <hr /> 
    """ 

# ---- Flask app ---- 

app = Flask(__name__) 

@app.route('/') 
def index(): 
    return make_html() 

counter = 0 
def eventgen(): 
    global counter 
    counter += 1  
    local_id = counter 
    msg_count = 0 
    while True: 
     msg_count += 1 
     data = {'msg': msg_count, 'content': random.random(), 'local_id': local_id} 
     data = json.dumps(data) 
     yield 'data: ' + data + '\n\n' 
     print local_id, ':', data 
     time.sleep(0.5) 

@app.route('/stream') 
def eventstream(): 
    return flask.Response(eventgen(), mimetype="text/event-stream") 

if __name__ == '__main__':  
    app.run(threaded=True) 
+4

Dường như tôi đã tìm thấy nguồn gốc của vấn đề này. Vấn đề có vẻ là với máy quét liên kết AVG và lá chắn firefox. Vô hiệu hóa lá chắn lướt sóng dường như để giải quyết vấn đề. Máy tính mà nó đã hoạt động đang chạy Avast thay cho AVG. Tôi đoán đây là một lỗi trong AVG, có lẽ nên được sửa. – mojoritty

+0

Giá trị thêm như là một câu trả lời đầy đủ - cảm ơn vì đã mang lại câu trả lời! –

Trả lời

3

Dường như tôi đã tìm thấy nguồn gốc của vấn đề này. Vấn đề có vẻ là với máy quét liên kết AVG và lá chắn firefox. Vô hiệu hóa lá chắn lướt sóng dường như để giải quyết vấn đề. Máy tính mà nó đã hoạt động đang chạy Avast thay cho AVG. Tôi đoán đây là một lỗi trong AVG, có lẽ nên được sửa.

+1

Bạn có thực sự chắc chắn, đó là một giải pháp hợp lý? Có vẻ như bạn đã cố định trên máy khách, điều gì đã gây hại cho máy chủ. Và một ứng dụng khách khác có cùng vấn đề sẽ gây ra sự cố trên máy chủ một lần nữa và không có gì bạn làm với máy khách bị định cấu hình sai hoặc thậm chí là độc hại. – allo

Các vấn đề liên quan