只要服务器上有数据,就在网页上显示结果 [英] Display the result on the webpage as soon as the data is available at server

查看:53
本文介绍了只要服务器上有数据,就在网页上显示结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Python编写cgi页面。假设某个客户向我的cgi页面发送了请求。我的cgi页会进行计算,并在获得第一个输出后立即将其发送回客户端,但会继续进行计算并发送其他响应之后 strong>发送第一个响应。

I am writing a cgi page in Python. Let's say a client sends request to my cgi page. My cgi page does the calculation and as soon as it has the first output, it sends back that output to the client, but it will CONTINUE to do the calculation and send other responses AFTER the first response is sent.

我在这里介绍的内容有可能吗?我之所以问这个问题,是因为据我所知,在cgi页面中,响应是一次性发送回去的,一旦发送响应,cgi-page就会停止运行。这东西是在服务器端还是客户端,我该如何实现?

Is what I have presented here possible? I ask this question because in my limited knowledge, in a cgi page responses are sent back on one-time basic, once a response is sent, cgi-page stops running. This thing is made on server side or client side, and how do I implement it?

我的服务器正在运行Apache。非常感谢你。

My server is running Apache. Thank you very much.

在此论坛中,我尝试了来自 dbr的客户端代码(由于他,我有了长轮询的工作原理)。

I have tried a client code from "dbr" in this forum (thanks to him I got the idea of how long-polling works).

<html>
<head>
    <title>BargePoller</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>

    <style type="text/css" media="screen">
      body{ background:#000;color:#fff;font-size:.9em; }
      .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
      .old{ background-color:#246499;}
      .new{ background-color:#3B9957;}
    .error{ background-color:#992E36;}
    </style>

    <script type="text/javascript" charset="utf-8">
    function addmsg(type, msg){
        /* Simple helper to add a div.
        type is the name of a CSS class (old/new/error).
        msg is the contents of the div */
        $("#messages").append(
            "<div class='msg "+ type +"'>"+ msg +"</div>"
        );
    }

    function waitForMsg(){
        /* This requests the url "msgsrv.php"
        When it complete (or errors)*/
        $.ajax({
            type: "GET",
            url: "msgsrv.php",

            async: true, /* If set to non-async, browser shows page as "Loading.."*/
            cache: false,
            timeout:50000, /* Timeout in ms */

            success: function(data){ /* called when request to barge.php completes */
                addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
                setTimeout(
                    'waitForMsg()', /* Request next message */
                    1000 /* ..after 1 seconds */
                );
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
                addmsg("error", textStatus + " (" + errorThrown + ")");
                setTimeout(
                    'waitForMsg()', /* Try again after.. */
                    "15000"); /* milliseconds (15seconds) */
            },
        });
    };

    $(document).ready(function(){
        waitForMsg(); /* Start the inital request */
    });
    </script>
</head>
<body>
    <div id="messages">
        <div class="msg old">
            BargePoll message requester!
        </div>
    </div>
</body>
</html>

这是我的服务器代码:

import sys
if __name__ == "__main__":
    sys.stdout.write("Content-Type: text/html\r\n\r\n")
    print "<html><body>"
    for i in range(10):
        print "<div>%s</div>" % i
        sys.stdout.flush()
    print "</body></html>"

我希望我的客户页面一次显示1个数字(0、1、2 、. ..),但数据总是一次全部显示出来(01234 ...)。请帮我弄清楚。非常感谢你们。

I am expecting my client page to display 1 number at a time (0,1,2,...), but the data always comes out all at once (01234...). Please help me figure it out. Thanks you guys so much.

只是有点偏离轨道,我试图使用jquery Comet插件,但是我找不到足够的文档。帮助将不胜感激。再次感谢:D

Just a little out-track, I am trying to use jquery comet plugin, but I couldn't find sufficient documentation though. Helps would be much appreciated. Thanks again :D

好的,最后感谢您的指导,我设法使它成功。当您预测mod_deflate是所有这些源头时,您是对的。

[edit] Ok guys, finally thanks to your guides I have managed to make it work. You're right when predict that mod_deflate is the source of all this.

总而言之,我在这里所做的事情:

To sum up, what I have done here:


  • 对于客户端,使用

  • For client, make a long poll page as the html code above

对于服务器,请通过以下方式禁用mod_deflate:编辑文件/ etc / apache2 / mods-available / deflate.conf,用text / html部分注释掉该行,然后重新启动服务器。为了确保Python本身不会缓冲输出,请在页面开头添加#!/ usr / bin / python -u。请记住,要在客户端上进行每次打印后,请使用sys.stdout.flush()。效果可能不是透明的,应该包括time.sleep(1)进行测试。 :D

For server, disable the mod_deflate by: editing file /etc/apache2/mods-available/deflate.conf, comment out the line with text/html part and restart the server. To ensure that Python doesn't buffer the output itself, include #!/usr/bin/python -u in the beginning of the page. Remember to use sys.stdout.flush() after each printing that you want to appear at the client. The effect may not be transparent, should include time.sleep(1) to test. :D

非常感谢你们支持和帮助解决此问题:D

Thanks you guys very much for supporting and helping solving this :D

推荐答案

可以。

有传统的服务器驱动方法,脚本只运行一次,但是需要需要花很长时间才能完成,所以会随心吐出页面的一部分:

There's traditional server-driven approach, where the script runs just once, but takes a long time to complete, spitting out bits of page as it goes:

import sys, time

sys.stdout.write('Content-Type: text/html;charset=utf-8\r\n\r\n')

print '<html><body>'
for i in range(10):
    print '<div>%i</div>'%i
    sys.stdout.flush()
    time.sleep(1)

向WSGI编写应用程序时,通过返回应用程序来完成一个可迭代的函数,一次输出要发送的每个块。我真的建议写WSGI;您现在可以通过CGI部署它,但是将来当您的应用需要更好的性能时,您可以通过更快的服务器/界面来部署它而不必重写。

When writing an app to WSGI, this is done by having the application return an iterable which outputs each block it wants sent separately one at a time. I'd really recommend writing to WSGI; you can deploy it through CGI now, but in the future when your app needs better performance you can deploy it through a faster server/interface without having to rewrite.

WSGI-过度CGI示例:

WSGI-over-CGI example:

import time, wsgiref.handlers

class MyApplication(object):
    def __call__(self, environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')])
        return self.page()

    def page(self):
        yield '<html><body>'
        for i in range(10):
            yield '<div>%i</div>'%i
            time.sleep(1)

application= MyApplication()
if __name__=='__main__':
    wsgiref.handlers.CGIHandler().run(application)

请注意,您的网站服务器可以通过添加自己的缓冲来挫败这种方法(对于CGI WSGI)。如果您使用 mod_deflate 这样的输出转换过滤器来自动压缩Webapp输出,通常会发生这种情况。您需要为生成部分响应的脚本关闭压缩。

Note that your web server may foil this approach (for CGI or WSGI) by adding buffering of its own. This typically happens if you're using output-transforming filters like mod_deflate to automatically compress webapp output. You'll need to turn compression off for partial-response-generating scripts.

这限制了您在输入新数据时逐位渲染页面。可以让客户端负责在新数据传入时更改页面,从而使其更漂亮,例如:

This limits you to rendering the page bit-by-bit as new data comes in. You can make it prettier by having the client-side take care of altering the page as new data comes in, eg.:

def page(self):
    yield (
        '<html><body><div id="counter">-</div>'
        '<script type="text/javascript">'
        '    function update(n) {'
        '        document.getElementById("counter").firstChild.data= n;'
        '    }'
        '</script>'
    )
    for i in range(10):
        yield '<script type="text/javascript">update(%i);</script>'%i
        time.sleep(1)

关于客户端脚本,因此最好在末尾包含基于非脚本的备份最终输出。

This relies on client-side scripting so it might be a good idea to include backup non-script-based final output at the end.

一直以来,该页面似乎仍在加载。如果您不希望这样做,则需要将脚本拆分为一个只发出静态内容的第一个请求,包括客户端脚本,该脚本使用一个轮询新数据的XMLHttpRequest与服务器进行核对在真正长期运行的情况下,很多XMLHttpRequest都会返回状态和任何新数据。这种方法要复杂得多,因为它意味着您必须将工作流程作为Web服务器之外的后台守护进程运行,并使用例如在守护程序和前端CGI / WSGI请求之间传递数据。管道或数据库。

All the while doing this, the page will appear to be still loading. If you don't want that, then you'd need to split the script into a first request that just spits out the static content, including client-side script that checks back with the server using either one XMLHttpRequest that it polls for new data through, or, for the really long-running cases, many XMLHttpRequests each of which returns the status and any new data. This approach is much more complicated as it means you have to run your work process as a background daemon process apart from the web server, and pass data between the daemon and the front-end CGI/WSGI request using eg. pipes or a database.

这篇关于只要服务器上有数据,就在网页上显示结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆