Запуск более одного сервера с использованием Python - PullRequest
0 голосов
/ 28 августа 2018

Я в основном пытаюсь запустить два сервера, используя простой скрипт. Я использовал решения от здесь , там и другие. Например, в приведенном ниже примере я пытаюсь разместить два каталога в портах 8000 и 8001.

import http.server
import socketserver
import os
import multiprocessing


def run_webserver(path, PORT):
    os.chdir(path)
    Handler = http.server.SimpleHTTPRequestHandler
    httpd = socketserver.TCPServer(('0.0.0.0', PORT), Handler)

    httpd.serve_forever()

    return


if __name__ == '__main__':

    # Define "services" directories and ports to use to host them
    server_details = [
        ("path/to/directory1", 8000),
        ("path/to/directory2", 8001)
    ]

    # Run servers
    servers = []
    for s in server_details: 
        p = multiprocessing.Process(
            target=run_webserver, 
            args=(s[0], s[1])
            )
        servers.append(p)  

    for server in servers:
        server.start()

    for server in servers:
        server.join()

После выполнения приведенного ниже кода все работает нормально, и я могу получить доступ к обоим каталогам, используя http://localhost:8000 и http://localhost:8001. Однако при выходе из сценария с помощью Ctrl + C и затем попробуйте снова запустить скрипт, я получаю следующую ошибку:

 Traceback (most recent call last):                                                                                     
 "/home/user/anaconda3/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap           
        self.run()                                                                                                         
      File "/home/user/anaconda3/lib/python3.6/multiprocessing/process.py", line 93, in run                   
        self._target(*self._args, **self._kwargs)                                                                          
      File "repos/scripts/webhosts.py", line 12, in run_webserver                                                          
      File "/home/user/anaconda3/lib/python3.6/socketserver.py", line 453, in __init__                        
        self.server_bind()                                                                                                 
      File "/home/user/anaconda3/lib/python3.6/socketserver.py", line 467, in server_bind                     
        self.socket.bind(self.server_address)                                                                              
    OSError: [Errno 98] Address already in use 

Эта ошибка появляется, только если я действительно получаю доступ к серверу во время работы. Если у меня нет доступа к нему, я могу перезапустить скрипт ... Из сообщения об ошибке похоже, что что-то все еще обращается к серверу при наборе lsof -n -i4TCP:8000 и lsof -n -i4TCP:8001 Я ничего не получаю ... И через некоторое время эта ошибка перестает появляться, и я действительно могу запустить скрипт.

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Расширение моего комментария:

В предыдущем редакторе OP зарегистрирован обработчик выхода atexit.register(exit_handler). Вопрос в том, очищает ли он ваши системные ресурсы (например, открытые сокеты)?

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

Использование обработчиков выхода - хороший способ избежать этого

import atexit
atexit.register(clean_sockets)

def clean_sockets():
    mysocket.server_close() #
0 голосов
/ 28 августа 2018

Перед запуском сервера добавьте:

socketserver.TCPServer.allow_reuse_address = True

или измените этот атрибут экземпляра еще раз перед вызовом serve_forever():

htttp.allow_reuse_address = True

Справочная документация :

BaseServer.allow_reuse_address

Будет ли сервер разрешать повторное использование адреса. По умолчанию используется значение False, и его можно установить в подклассах для изменения политики.

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