Как доставить экземпляр объекта в экземпляр SocketServer.BaseRequestHandler? - PullRequest
2 голосов
/ 02 апреля 2009

Это проблема. Моя основная работа: доставить объект "s" методу "handle" в классе TestRequestHandler. Моим первым шагом было: доставить объект "s" через метод "point" в класс 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 ]

2 голосов
/ 03 апреля 2009

Если я правильно понимаю, я думаю, что вы, возможно, неправильно понимаете, как работает модуль. Вы уже указали адрес «localhost: 6666» для сервера, к которому нужно привязаться.

Когда вы запускаете сервер через ваш вызов serve_forever (), это приведет к тому, что сервер начнет прослушивать сокет на localhost: 6666.

Согласно документации, этот сокет передается вашему RequestHandler как объект 'request'. Когда данные получены в сокете, ваш метод handle должен иметь возможность получать / отправлять данные из / в этот объект, используя документированный API сокетов.

Если вам нужна дополнительная абстракция, похоже, ваш RequestHandler может расширяться из StreamRequestHandler и выполнять чтение / запись в сокет с использованием файловых объектов.

Дело в том, что вам не нужно создавать дополнительный сокет, а затем пытаться заставить свой сервер использовать новый. Часть ценности модуля SocketServer заключается в том, что он управляет жизненным циклом сокета.

С другой стороны, если вы хотите протестировать свой сервер с точки зрения клиента, вы захотите создать сокет, на котором вы можете читать / записывать ваши клиентские запросы. Но вы бы никогда не передали этот сокет на свой сервер, по сути. Вероятно, вы сделаете это в совершенно отдельном процессе и протестируете свой сервер через IPC через сокет.

Редактирование на основе новой информации

Чтобы заставить сервер A открывать сокет для сервера B, когда сервер A получает данные, одним из решений является просто открыть сокет внутри вашего 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, так что ваш обработчик сервера A может просто получить / освободить сокет при обработке входящих запросов.

Таким образом, вы можете лучше справляться с условиями, когда сервер B ломает сокет. Ваш нынешний дизайн не сможет справиться со сломанными розетками очень легко. Просто некоторые мысли ...

1 голос
/ 03 апреля 2009

Хорошо, моя главная задача заключается в следующем. Построение слушающего сервера (A-сервер - localhost, 6666), который во время запуска откроет «жесткое» соединение с другим сервером (B-сервер - localhost, 7777). Когда клиент отправляет данные на A-сервер, он (A-сервер) отправляет данные (имеющие жесткое соединение с B-сервером) на B-сервер, ответ получает от B-сервера на A-сервер, а ответ отправляет на клиент. Затем снова: клиент отправляет данные, A-сервер получает их, затем отправляет на B-сервер, ответ получает данные от B-сервера, а A-сервер отправляет данные клиенту. И так по кругу. Соединение с B-сервером закрывается только тогда, когда сервер A остановится. Все вышеперечисленное - это тест на создание этого.

1 голос
/ 02 апреля 2009

Если значение s установлено один раз, а не инициализировано повторно - вы можете сделать его переменной класса в отличие от переменной экземпляра TestServer, а затем обработчик получит его с помощью метода класса TestServer в конструкторе обработчика.

Например: TestServer._mySocket = s

...