python单线程服务器如何处理多客户端

时间:2013-01-24 15:38:19

标签: python client-server django-views

我在python中有一个提供页面的服务器。使用IdP(身份提供商)完成对这些页面的登录。因此,当用户尝试打开我的服务器页面时,他将被重定向到IdP页面。同时我的服务器开始监听IdP响应。当用户登录IdP页面时,IdP会将数据发送到我的服务器,处理它们并向用户显示我的页面。

问题是,如果多个客户端尝试登录,当服务器收到来自一个IdP的第一个响应时,所有用户将显示我的页面,并使用第一个用户的凭据登录。

我的意思是,当服务器开始收听时,它正在等待所有人。当只有第一个用户登录时,所有等待使用相同凭据记录的用户。

如何解决这个非常大的问题?多线程可能有帮助吗?

这里有一些重要的代码。假设我想将idp应答的一些数据加载到我页面登录表单的字段“名称”中。

class Login(django.forms.SelfHandlingForm):
    def __init__(self, *args, **kwargs):
        super(Login, self).__init__(*args, **kwargs)
        response = self.getIdPResponse()
        self.fields['name'].widget=forms.TextInput(attrs={'value': response['name']})


    def getIdPResponse(self):
        global response
        response = None
        timeout = 300
        class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
            def do_POST(self):
                global response
                self.send_response(200)
                self.send_header("Content-type", "text/html")
                self.end_headers()
                varLen = int(self.headers["Content-Length"])
                #response = urlparse.parse_qs(self.rfile.read(varLen))
                response = self.rfile.read(varLen)

                self.wfile.write("Log-in ok! now you can close this page.")
        httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 8080), RequestHandler)
        try:
            httpd.socket.settimeout(1)
        except BaseException as e:
            print e
        count = 0
        '''at this point, the IdP page is already showed to the user '''
        while response is None and count < timeout:
           try:
               httpd.handle_request()
               count = count + 1
               print 'waiting for the Idp answer...'
           except Exception as e:
               print e
        return response

这样,当用户成功登录时,所有等待登录的用户都会在字段'name'中显示首次登录的用户名。显然我不想这样。

1 个答案:

答案 0 :(得分:0)

一种方法是使用事件驱动的系统(如twisted)将getIdPResponse方法拆分为两部分:

  1. 发送请求
  2. 处理回复
  3. 然后您的单个线程不会阻塞,并且可以在此期间为其他客户端分派事件。

    如果你想简化你的应用程序逻辑,可以包装一层阻塞调用,但这不是我推荐的。