TCPServer + BaseRequestHandler в SocketServer Python закрывает сокет после каждого вызова метода handle ()? - PullRequest
9 голосов
/ 14 января 2010

Я пишу клиент-серверное приложение на Python и считаю необходимым устанавливать новое соединение с сервером для каждого запроса от клиента. Мой сервер просто наследуется от TCPServer, а я наследую от BaseRequestHandler, чтобы выполнить мою обработку. Я не вызываю self.request.close () в обработчике, но сервер почему-то зависает на моем клиенте. Что случилось?

Ответы [ 4 ]

8 голосов
/ 15 января 2010

Хорошо, я прочитал код (на моем Mac SocketServer.py находится по адресу /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/).

Действительно, TCPServer закрывает соединение. В BaseServer.handle_request вызывается process_request, что вызывает close_request. В классе TCPServer close_request вызывает self.request.close(), а self.request - просто сокет, используемый для обработки запроса.

Так что ответ на мой вопрос "Да".

6 голосов
/ 28 июля 2010
  1. tcpserver действительно закрывает соединение каждый раз после 'handle'
  2. следующий код не работает при закрытии пира

    def handle(self):
        while 1:
        try:
            data = self.request.recv(1024)
            print self.client_address, "sent", data
        except:
            pass
    

    это может быть лучше:

    def handle(self):
        while(1):
            try:
                self.data = self.request.recv(1024)
                if not self.data:
                    print "%s close" % self.client_address[0]
                    break
                print "%s wrote:" % self.client_address[0], self.data
            except:
                print "except"
                break
    
    1. reuseaddr не работает, так как слишком поздно после привязки
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
6 голосов
/ 15 января 2010

Согласно документам , ни TCPServer, ни BaseRequestHandler не закрывают сокет, если не будет предложено сделать это. Реализации по умолчанию handle() и finish() ничего не делают.

Может произойти пара вещей:

  • Вы закрываете сам сокет или запрос, который его оборачивает, или вызываете server_close где-то.
  • Возможно, истекло время ожидания сокета, и вы реализовали обработчик времени ожидания, который закрывает сокет.
  • Клиент мог фактически закрывать сокет. Код действительно помог бы понять это.

Однако , мое тестирование подтверждает ваши результаты. Как только вы вернетесь с сервера handle на сервере, независимо от того, подключаетесь ли вы через telnet или модуль Python socket, ваше подключение будет показано удаленным хостом как закрытое. Кажется, работает обработка активности сокета в цикле внутри дескриптора:

def handle(self):
    while 1:
        try:
            data = self.request.recv(1024)
            print self.client_address, "sent", data
        except:
            pass

Краткий поиск кода Google подтверждает, что это типичный способ обработки запроса: 1 2 3 4 . Честно говоря, существует множество других сетевых библиотек, доступных для Python, на которые я мог бы обратить внимание, если бы столкнулся с разрывом между абстракцией SocketServer и моими ожиданиями.

Пример кода, который я использовал для проверки:

from SocketServer import BaseRequestHandler, TCPServer

class TestRequestHandler(BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024)
        print self.client_address, "sent", data
        self.request.send(data)

class TestServer(TCPServer):
    def __init__(self, server_address, handler_class=TestRequestHandler):
        TCPServer.__init__(self, server_address, handler_class)

if __name__ == "__main__":
    import socket

    address = ('localhost', 7734)
    server = TestServer(address)
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
0 голосов
/ 14 января 2010

Вы уверены, что клиент не зависает на сервере? Это слишком расплывчато, чтобы действительно сказать, что случилось, но обычно сервер, принимающий данные от клиента, выйдет из соединения чтения и не вернет никаких данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...