Закрыть / перезапустить сокет в Python - PullRequest
1 голос
/ 17 февраля 2011

Я собираюсь провести простую тестовую реализацию с использованием PagSeguro (бразильский "PayPal"), и для этого я скачал их сервер Python для тестирования на моем локальном хосте. Я работаю на Mac, у меня есть сервер XAMPP (части Apache и MySQL во время моего процесса).

Моя проблема должна быть очень простой для тех, кто знает Python, сокеты и т. Д., И я нашел много подсказок в моих поисках информации. Однако - из-за моих слабых знаний в этой области я не смог соединить два и два, чтобы это исправить.

Короткий вопрос: как освободить сокет (из Терминала), чья программа вышла до того, как закрыла сокет. Alt - как мне сделать функцию Python для меня вызывающей, когда я хочу закрыть сокет и остановить / перезапустить сервер.

Сценарий: Я запускаю сервер (в терминале с #: sudo python ./PagSeguroServer.py), и он работает нормально, я сделал несколько тестов, которые хотел. Затем мне нужно было изменить некоторые настройки сервера, и чтобы он работал, мне нужно перезагрузить сервер. Я решил, закрыв окно терминала, но затем, когда я снова открываю и набираю ту же команду, чтобы снова запустить сервер, я получаю «socket.error: [Errno 48] Адрес уже используется». Хорошо, я могу понять, почему, но не как это исправить, поэтому я гуглю это и нахожу подсказку для добавления

socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

в коде. Посмотрел класс Python и попытался поставить его там, насколько мне известно (как показано ниже). Тем не менее, не решил мою проблему. Так как мой «поиск и загадка», кажется, не в состоянии помочь мне - я сейчас бросаю его и вместо этого публикую этот персонализированный вопрос!

Это часть кода сервера:

class SecureHTTPServer(HTTPServer):
    '''Servidor HTTPS com OpenSSL.'''
    def __init__(self, server_address, HandlerClass,fpem):
        BaseServer.__init__(self, server_address, HandlerClass)
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        ctx.use_privatekey_file (fpem)
        ctx.use_certificate_file(fpem)
        self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
                                                        self.socket_type))
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_bind()
        self.server_activate()

    ....

def run(HandlerClass = HTTPSHandler, ServerClass = SecureHTTPServer):
    '''Roda o servidor'''
    server_address = ('', 443) # (address, port)
    httpd = ServerClass(server_address, HandlerClass, fpem)
    httpd.serve_forever()

if __name__ == '__main__':
    run()

Примечание: Однажды мне действительно удалось открыть его - это было до того, как я добавил вызов setsockopt, и у меня возникло ощущение, что сокет закрылся после тайм-аута - где-то читал об этом. Это, однако, похоже, больше не повторится - ждали и пытались несколько раз.

Редактировать: В конце концов, я решил это следующим образом: необходимо убить процесс python, который удерживал сокет (см. Комментарий к ответу jd), затем добавил перехват KeyboardInterrupt, чтобы иметь возможность правильно закрыть сокет. Спасибо всем!

Ответы [ 4 ]

1 голос
/ 17 февраля 2011

Вы можете создать функцию, которая правильно закрывает сокет и регистрирует ее для запуска при завершении программы, используя atexit.register(). Смотри http://docs.python.org/library/atexit.html

0 голосов
/ 07 февраля 2013

В OSX вы можете уничтожить порт (например, 8000) с помощью:

kill `lsof -i: 8000 |grep Python |cut -c8-11`

hth

0 голосов
/ 17 февраля 2011

AFAIR SO_REUSEADDR работает немного по-другому.

Но с чего вам следует начать - когда вы убьете свой рабочий сервер, наберите

netstat -tapdn | grep PORT

и заменитеПОРТ с ПОРТОМ вашего приложения

Чем вы получите информацию о состоянии сокета ....

0 голосов
/ 17 февраля 2011

Если вы используете Ctrl + C для закрытия процесса, вы можете попытаться перехватить исключение KeyboardInterrupt (или, что еще лучше, обработать сигнал SIGINT) в своем коде и аккуратно закрыть сокет перед выходом.

Конечно, это не помешает вам убить ваше приложение каким-либо другим способом и иметь устаревший сокет, но вы также можете попытаться обработать эти случаи.

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