如何将对象的实例传递给SocketServer.BaseRequestHandler的实例?

时间:2009-04-02 18:26:58

标签: python python-2.7 sockets tcp socketserver

这是问题所在。 我的主要工作是:在TestRequestHandler类中将“s”对象传递给“handle”方法。 我的第一步是:通过“点”方法将“s”对象传递给TestServer类,但是这里我卡住了。如何将“s”对象传递给TestRequestHandler?一些建议?

import threading
import SocketServer
from socket import *

class TestRequestHandler(SocketServer.BaseRequestHandler):

    def __init__(self, request, client_address, server):
        SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)
        return

    def setup(self):
        return SocketServer.BaseRequestHandler.setup(self)

    def handle(self):
        data = self.request.recv(1024)

        if (data): 
            self.request.send(data)
            print data

    def finish(self):
        return SocketServer.BaseRequestHandler.finish(self)

class TestServer(SocketServer.TCPServer):

    def __init__(self, server_address, handler_class=TestRequestHandler):
        print "__init__"
        SocketServer.TCPServer.__init__(self, server_address, handler_class)
        return

    def point(self,obj):
        self.obj = obj
        print "point"

    def server_activate(self):
        SocketServer.TCPServer.server_activate(self)
        return

    def serve_forever(self):
        print "serve_forever"
        while True:
            self.handle_request()
        return

    def handle_request(self):
        return SocketServer.TCPServer.handle_request(self)

if __name__ == '__main__':

    s = socket(AF_INET, SOCK_STREAM)

    address = ('localhost', 6666)
    server = TestServer(address, TestRequestHandler)
    server.point(s)
    t = threading.Thread(target=server.serve_forever())
    t.setDaemon(True)
    t.start()

3 个答案:

答案 0 :(得分:2)

如果我理解正确,我想你或许误解了模块是如何工作的。您已经为要绑定的服务器指定了“localhost:6666”的地址。

当您通过调用serve_forever()启动服务器时,这将导致服务器开始侦听localhost:6666上的套接字。

根据文档,该套接字作为“请求”对象传递给您的RequestHandler。当在套接字上收到数据时,你的'handle'方法应该能够使用记录的套接字API从/向该对象发送/发送。

如果你想进一步抽象,看起来你的RequestHandler可以使用类似文件的对象从StreamRequestHandler和读/写扩展到套接字。

关键是,您无需创建额外的套接字,然后尝试强制您的服务器使用新的套接字。 SocketServer模块的部分价值在于它为您管理套接字的生命周期。

另一方面,如果您想从客户端的角度测试服务器,那么您可能希望创建一个可以读取/写入客户端请求的套接字。但是你永远不会将这个套接字传递给你的服务器。您可能会在一个完全独立的过程中执行此操作,并通过套接字通过IPC测试您的服务器。

根据新信息进行修改

要让服务器A在服务器A接收数据时打开服务器B的套接字,一个解决方案就是从RequestHandler内部打开一个套接字。也就是说,根据您的服务要求,您可能需要解决一些其他设计问题。

例如,您可能希望使用一个简单的连接池,即向服务器B打开几个套接字,服务器A可以像资源一样使用它。 Python中可能已经有一些库可以帮助解决这个问题。

鉴于您当前的设计,您的RequestHandler可以作为成员变量访问服务器,因此您可以执行以下操作:

class TestServer(SocketServer.TCPServer):
     def point (self, socketB):
         self.socketB = socketB # hold serverB socket

class TestRequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        data = self.request.recv(1024)

        if (data): 
            self.request.send(data)
            print data

        self.server.socketB ... # Do whatever with the socketB

但就像我说的那样,你可能更好地拥有某种连接池或管理服务器B套接字的其他对象,这样你的服务器处理程序就可以在处理传入请求时获取/释放套接字。 / p>

这样您就可以更好地处理服务器B断开套接字的情况。您当前的设计无法轻松处理损坏的插座。只是一些想法...

答案 1 :(得分:1)

如果s的值设置一次,而不是重新初始化 - 你可以使它成为一个类变量而不是TestServer的实例变量,然后让处理程序通过处理程序构造函数中的TestServer类方法检索它。

例如:TestServer._mySocket = s

答案 2 :(得分:1)

好的,我的主要任务是这个。构建监听服务器(A-server-localhost,6666),在启动期间将打开与不同服务器(B-server-localhost,7777)的“硬”连接。 当客户向A服务器发送数据时(A服务器)将数据(具有与B服务器的硬连接)发送到B服务器,答案从B服务器接收到A服务器并且应答发送到顾客。 然后:客户发送数据,A服务器接收数据,然后发送到B服务器,答案从B服务器接收数据,A服务器向客户发送数据。 如此圆润。只有当服务器A停止时才会关闭与B服务器的连接。 以上都是做这个的考验。