python - 使用 SSE + 长轮询创建 Web 应用程序时出现的问题

标签 python long-polling server-sent-events

我是网络开发新手。我正在为我的家庭自动化项目创建一个网络应用程序,其中我需要双向通信。任何来自家的盗窃安全警报都将从服务器发送到客户端,或者如果客户端想要控制大门,他将向服务器发送 POST 请求。我仍然很困惑该使用什么,SSE 还是 Web 套接字。我的问题是,是否可以开发一个既使用 SSE 又处理来自客户端 (GET/POST) 的传统(长轮询)HTTP 请求的应用程序?我已经单独测试了它们,它们工作得很好,但我无法让它们一起工作。我正在使用 python BaseHTTPServer。或者最后,我必须转向 WebSocket 吗?任何建议将受到高度赞赏。我的代码是;

import time
import BaseHTTPServer
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn

import os
import requests
import threading
from threading import Thread
from chk_connection import is_connected
import socket


HOST_NAME = socket.gethostbyname(socket.gethostname())
PORT_NUMBER = 8040 # Maybe set this to 9000.
ajax_count=0
ajax_count_str=""
switch=0
IP_Update_time=2 
keep_alive=0
connected=False


###############################

##############

my_dir = os.getcwd()


class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
 def do_HEAD(s):
    s.send_response(200)
    s.send_header("Content-type", "text/html")
    s.end_headers()



def do_POST(s):

    global keep_alive

    """Respond to a POST request."""
    s.send_response(200)
    s.send_header('Access-Control-Allow-Origin', '*')
    s.send_header("Content-type", "text/html")
    s.end_headers()
    HTTP_request=s.requestline

    if HTTP_request.find('keep_alive')>-1:
             keep_alive += 1
             keep_alive_str = str(keep_alive)
             s.wfile.write(keep_alive_str)  #sending ajax calls for keep alive 




def do_GET(s):
    global ajax_count
    global my_dir
    global switch
    global ajax_count_str
    global keep_alive
    #print 'got Get',
    """Respond to a GET request."""
    s.send_response(200)
    #s.send_header('Access-Control-Allow-Origin', '*')
    s.send_header('content-type', 'text/html')
    s.end_headers()
    print s.headers
    HTTP_request=s.requestline
    index_1=HTTP_request.index("GET /")
    index_2=HTTP_request.index(" HTTP/1.1")
    file_name=HTTP_request[index_1+5:index_2]
    #print 'file_name:',file_name
    #print 'HTTP_request:',HTTP_request 
    #if len(file_name)>0:

    #if HTTP_request.find('L2ON')>-1:
    #        print 'sending SSE'
    #        s.wfile.write('event::'.format(time.time()))




    elif HTTP_request.find('GET / HTTP/1.1')>-1: 
        print 'send main'
        file1=open('Index.html','r')
        file_read=file1.read()
        s.wfile.write(file_read)


    elif file_name.find("/")==-1:
           for root, dirs, files in os.walk(my_dir):
               #print 'in for 1' 
               for file in files:
                 #print 'in for'  
                 if HTTP_request.find(file)>-1:
                    file_path=os.path.join(root,file)
                    file1=open(file_path,'r')
                    file_read=file1.read()
                    s.wfile.write(file_read)
                    print 'send',file

    elif file_name.find("/")>-1:
             #print 'get /...'
             slash_indexes=[n for n in xrange(len(file_name)) if file_name.find('/', n)==n]
             length=len(slash_indexes)
             slash=slash_indexes[length-1]
             file_path=file_name[0:slash]
             root_dir=(my_dir + '/' + file_path + '/')
             for root, dirs, files in os.walk(root_dir): 
               for file in files: 
                  if HTTP_request.find(file)>-1:
                    image_path=os.path.join(root,file)
                    image=open(image_path,'r')
                    image_read=image.read()
                    s.wfile.write(image_read)
                    print 'send',file
                  #else:
                    #print 'file not found'


class MyHandler_SSE(BaseHTTPRequestHandler):
 print 'SSE events class'
 def do_GET(self):
    print 'this is SSE'
    self.send_response(200)
    self.send_header('content-type', 'text/event-stream')
    self.end_headers()
    while True:
        print 'SSE sent'
        self.wfile.write('event: message\nid: 1\ndata: {0}\ndata:\n\n'.format(time.time()))
        time.sleep(2)





class chk_connection(threading.Thread):
  """
  # this thread checks weather there is internet connection available ? 
  """
  def __init__(self):
    threading.Thread.__init__(self)

  def run(self):
    global connected
    while 1:
     ########################################################## INSIDE THE            chk_connection import is_connected
    #import socket
    #REMOTE_SERVER = "www.google.com"
    #def is_connected():
    #try:
    #   # see if we can resolve the host name -- tells us if there is
    #   # a DNS listening
    #   host = socket.gethostbyname(REMOTE_SERVER)
        # connect to the host -- tells us if the host is actually
        # reachable
    #   s = socket.create_connection((host, 80), 2)
    #   return True
    #except:
    #   pass
    #return False
     ##########################################################
        connected=is_connected()
        #print 'internet:', connected
        time.sleep(1)


class server_main(threading.Thread):
 """


 """
 def __init__(self):
    threading.Thread.__init__(self)


 def run(self):
    global connected


    #print 'shutdown started'
    server_class = BaseHTTPServer.HTTPServer
    HOST_NAME = socket.gethostbyname(socket.gethostname())
    last_HOST_NAME = HOST_NAME
    httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)
    #http_SSE = server_class((HOST_NAME, PORT_NUMBER), MyHandler_SSE)
    print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
    while(1):       
      while is_connected():
        httpd._handle_request_noblock()
        #print 'no block'
        #http_SSE._handle_request_noblock()
      time.sleep(1)  
      HOST_NAME = socket.gethostbyname(socket.gethostname())
      if HOST_NAME != last_HOST_NAME:
          print 'Serving at new host:', HOST_NAME
      httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)  


def start():

tx_socket_thread3 = chk_connection()   # this thread checks weather there is internet connection available ?
tx_socket_thread3.start()

tx_socket_thread5 = server_main()
tx_socket_thread5.start()
print 's1:',tx_socket_thread1.is_alive()

if __name__ == '__main__':

 start()

我可能需要以新的方式修改代码,但不知道如何修改。我想要的是,如果服务器端发生任何中断,它会将数据拉到客户端,同时它也响应来自客户端的 GET 和 POST 请求。帮助PLX...

最佳答案

开发一个混合使用普通 HTTP 流量、服务器端事件和 WebSocket 的 Web 应用程序是绝对可能的。然而,Python 标准库中的 Web 服务器类并不是为此目的而设计的,尽管可以通过足够的锤炼使它们工作。您应该安装适当的网络服务器并使用它的设施。

示例包括

此外

关于python - 使用 SSE + 长轮询创建 Web 应用程序时出现的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32679834/

相关文章:

python - wx.NotificationMessage 属性错误: 'module' object has no attribute 'NotificationMessage'

python - 如何绘制颜色 QtGui.QPainterPath.addRect()?

.net - 在 .NET 中对 WinForms 客户端使用长轮询

java - 将 "stream"Google Pub/Sub 消息直接发送到前端的最佳方式?服务器发送的事件?

php - 服务器发送的事件停止以新参数开始

python - Pyspark:Pad Array[Int] 列带零

python - 如何在 Tkinter 中强制调整顶级窗口的大小?

asp.net-mvc - .Net 中 LongPolling 的可扩展性 :Grand Finale

php - Nginx 作为长轮询时的反向代理

PHP内置网络服务器运行速度很慢