Почему Linux может принимать сокеты в многопроцессорности?

Этот код отлично работает в Linux, но не работает под Windows (что ожидается). Я знаю, что многопроцессорный модуль использует fork() для создания нового процесса, и файловые дескрипторы, принадлежащие родительскому объекту (то есть открытый сокет), поэтому унаследованы дочерним элементом. Тем не менее, я понимаю, что единственный тип данных, которые вы можете отправлять посредством многопроцессорной обработки, должен быть разборчивым. В Windows и Linux объект сокета не является подходящим.

 from socket import socket, AF_INET, SOCK_STREAM import multiprocessing as mp import pickle sock = socket(AF_INET, SOCK_STREAM) sock.connect(("www.python.org", 80)) sock.sendall(b"GET / HTTP/1.1\r\nHost: www.python.org\r\n\r\n") try: pickle.dumps(sock) except TypeError: print("sock is not pickleable") def foo(obj): print("Received: {}".format(type(obj))) data, done = [], False while not done: tmp = obj.recv(1024) done = len(tmp) < 1024 data.append(tmp) data = b"".join(data) print(data.decode()) proc = mp.Process(target=foo, args=(sock,)) proc.start() proc.join() 

Мой вопрос заключается в том, почему объект socket , явно непродуманный объект, должен быть передан с многопроцессорной обработкой? Разве это не использует рассол, как делает Windows?

2 Solutions collect form web for “Почему Linux может принимать сокеты в многопроцессорности?”

На платформах unix сокеты и другие файловые дескрипторы могут быть отправлены в другой процесс с использованием сокетов unix domain (AF_UNIX), поэтому сокеты можно травить в контексте многопроцессорности.

Модуль многопроцессорности использует специальный экземпляр сортировочного устройства вместо обычного pickler, ForkingPickler , для рассортирования сокетов и дескрипторов файлов, которые затем могут быть разбросаны в другом процессе. Это можно сделать только потому, что известно, что маринованный экземпляр будет разбросан, не имеет смысла рассортировать сокет или файловый дескриптор и отправлять его между границами машины.

Для окон существуют аналогичные механизмы для открытых дескрипторов файлов.

Я думаю, проблема заключается в том, что для multiprocessing используется другой сортировщик для систем Windows и других ОС. В Windows нет реальной fork() , и травление, которое выполняется, эквивалентно травлению через границы машины (т.е. распределенные вычисления). В системах, отличных от Windows, объекты (например, дескрипторы файлов) могут быть разделены между границами процесса. Таким образом, травление на системах Windows (с pickle ) является более ограниченным.

В пакете multiprocessing используется copy_reg для регистрации нескольких типов объектов для pickle , а один из этих типов – socket . Однако сериализация объекта socket который используется в Windows, более ограничена из-за слабой разборчивости Windows.

В соответствующей заметке, если вы хотите отправить объект socket с multiprocessing в Windows, вы можете … вам просто нужно использовать multiprocess пакет, который использует dill вместо pickle . dill имеет лучший сериализатор, который может разжевывать объекты socket на любой ОС и, таким образом, отправляет объект socket с multiprocess работами в любом случае.

dill имеет функцию copy ; в основном loads(dumps(object)) которые полезны для проверки объекта, могут быть сериализованы. dill также имеет check , который выполняет copy но с более ограничительной вилкой типа «Windows». Это позволяет пользователям в системах, отличных от Windows, эмулировать copy в системе Windows или распределенных ресурсах.

 >>> import dill >>> import socket >>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> s.connect(('www.python.org', 80)) >>> s.sendall(b'GET / HTTP/1.1\rnHost: www.python.org\r\n\r\n') >>> >>> dill.copy(s) <socket._socketobject object at 0x10e55b9f0> >>> dill.check(s) <socket._socketobject object at 0x1059628a0> >>> 

Короче говоря, разница вызвана сортировщиком, который использует multiprocessing в Windows, отличной от сортировочной машины, используемой в системах, отличных от Windows. Тем не менее, можно (и легко) работать над любой ОС, используя лучший сериализатор (как используется в multiprocess ).

  • Использование «запросов» Python с существующим подключением сокетов
  • Как исправить socket.gaierror: (11004, «getaddrinfo failed») ошибка в GAE?
  • Как я могу ответить на запрос метода CONNECT на прокси-сервере, используя сокет в python?
  • Выключение и повторная привязка сокета - Как избежать долгого ожидания?
  • Простой сервер python с использованием SimpleHTTPServer и SocketServer, как мне закрыть сокет до перезапуска файла .py?
  • Как закрыть соединение сокета на Ctrl-C в программе python
  • Почему это соединение сокета разрешает только 1 отправку и получение?
  • Можно ли отправлять асинхронные уведомления с сервера на клиент через те же TCP-соединения?
  • Вопрос клиента / сервера Python
  • ZMQ: нет подписного сообщения в гнезде XPUB для нескольких подписчиков (шаблон кэширования последнего значения)
  • SocketServer.ThreadingTCPServer - не удается привязать адрес после перезагрузки программы
  • Python - лучший язык программирования в мире.