JoCaml: проблемы с удаленным подключением - PullRequest
3 голосов
/ 06 марта 2011

(Возможно, для ответа на это достаточно знания библиотеки Unix, поэтому, пожалуйста, продолжайте читать, если вы не знаете JoCaml.)

У меня есть две программы в JoCaml . Сервер, готовый вернуть квадрат числа на порту 12345

(* p.ml *)
def f (x) =
        print_string ("["^string_of_int(x)^"] "); flush stdout;
        reply x*x to f
in Join.Ns.register Join.Ns.here "square" f
;;
let wait =
        def x () & y () = reply to x
        in x
let main =
        Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345));
        wait()

и клиент, готовый использовать функцию квадрата сервера

(* q.ml *)
let server =
        let server_addr = Unix.gethostbyname "192.168.0.10" in
        Join.Site.there (Unix.ADDR_INET(server_addr.Unix.h_addr_list.(0),12345))
let ns = Join.Ns.of_site server
let sqr = (Join.Ns.lookup ns "square": int -> int)
let _ = Printf.printf "%d\n" (sqr 3)

Это все работает нормально, если две программы работают на одном компьютере. Но моя цель - поместить их в две разные машины. Таким образом, IP выше должен стать другим публичным IP. Поскольку у меня есть только один компьютер для тестирования, я решил запустить две программы на этом компьютере и вместо общедоступного IP-адреса моей машины записать вместо 192.168.0.10 выше. К сожалению, это не работает, время ожидания истекло.

Есть идеи?

[Изменено]

Подробнее о проблеме

Код, который я написал выше, является примером, который я взял из руководства JoCaml, поскольку это была аналогичная и упрощенная версия моего собственного фрагмента кода, где возник вопрос. Программа, которую я пишу, направлена ​​на создание P2P-сети из сред времени выполнения JoCaml, которая все делает частные вычисления и хранит свои результаты локально, полагаясь на данные, хранящиеся в других узлах сети. Итак, я хочу, чтобы все одноранговые узлы выполняли что-то «похожее» на q.ml, так как им нужно подключаться к другим машинам и получать от них нужную информацию.

Каждый пэр должен иметь список своих пиров. Затем вы можете запросить сеть для некоторого значения простым способом. Каждый узел будет проверять, знает ли он это значение: если да, то возвращает его, если нет, то запрашивает его узлы (и так далее, рекурсивно). Архитектура P2P действительно хороша для моих целей. (Централизованная топология, предложенная Жилем, не будет работать для моей конкретной проблемы из-за проблем с производительностью и надежностью, упомянутых в его ответе.) Я ввел специальный одноранговый узел начальной загрузки, о котором знает весь код, и к которому любой новый узел сначала подключится. получить доступ к сети. Как только новый узел аутентифицирован узлом начальной загрузки, он должен присоединиться к сети и сам стать первоклассным узлом (и с этого момента может игнорировать узел начальной загрузки). Все эти одноранговые узлы будут напрямую взаимодействовать между собой (1-1), поэтому для каждой произвольной пары одноранговых узлов должен быть способ установить связь между ними. Кроме того, поскольку я хотел бы, чтобы кто-либо с соответствующими учетными данными мог присоединиться к этой сети, независимо от их сетевых навыков, у меня не может быть решения, где люди должны были бы настроить свой маршрутизатор для подключения к сети P2P. Они должны просто запустить программное обеспечение из коробки.

Мои требования тогда:

  1. P2P сеть одноранговых узлов в Интернете (то есть 1-1 соединение между любыми двумя узлами)
  2. одноранговые узлы могут находиться за непрозрачными маршрутизаторами
  3. нет конфигурации локального маршрутизатора
  4. специальный узел начальной загрузки, к которому вы впервые подключаетесь и аутентифицируетесь

То, что у меня сейчас есть, работает хорошо, если нам не требуется 2. Есть предложения по решению исходной проблемы, но в этом контексте P2P?

(Обратите внимание, что инфраструктура P2P - это всего лишь средство для достижения цели. Да, я хотел бы иметь что-то, что хорошо работает, но я не собираюсь разрабатывать окончательную супер-общую платформу P2P для JoCaml. I ' хочу написать простую вещь, которая просто выполняет свою работу.)

Ответы [ 2 ]

2 голосов
/ 06 марта 2011

(Я думаю, что ваша проблема связана с топологией IP-сети, а не с программированием как таковым, но вы должны понимать этот фон для программирования в JoCaml.)

Давным-давно,у каждого компьютера в Интернете был свой IP-адрес, и вы могли бы общаться с этим компьютером, если знали его IP-адрес.(Маршрутизаторы имеют один IP-адрес на интерфейс, но это касается только сетевых администраторов.) А, для простоты старых добрых времен.

Теперь все стало сложнее.Обычно компьютеры в интрасети имеют адрес, действительный только в этой интрасети, так называемый частный адрес .192.168.0.10 такой частный адрес.Вы можете разговаривать только с компьютером с частным адресом из этой интрасети.Когда компьютеру необходимо подключиться к внешней сети, преобразование сетевых адресов (NAT) используется для выполнения определенного подключения.NAT дает компьютеру интрасети общедоступный адрес, но он действителен только для определенного соединения.

Я подозреваю, что топология сети, с которой вы столкнулись, выглядит следующим образом, где A - ваш компьютер, C - этодругой компьютер, с которым вы в конечном итоге будете работать, R - это домашний или офисный маршрутизатор, а 1.2.3.4 - это то, что вы называете общедоступным IP-адресом вашей машины (фактически, вашей сети):

C [5.6.7.8] ←———→ [1.2.3.4] R [192.168.0.1] ←———→ [192.168.0.10] A

InВ этой ситуации C не может общаться с A, используя адрес 192.168.0.10, потому что этот адрес имеет значение только для интрасети.Если C вообще может общаться с A, он должен использовать 1.2.3.4, а R должен быть настроен на ретрансляцию пакетов, адресованных с 1.2.3.4 на A (в типичных конфигурациях R будет выполнять толькоэто на определенных портах TCP или UDP, если вообще).Но A не может разговаривать сам с собой, используя 1.2.3.4 в качестве адреса: если он идет изнутри, то, скорее всего, он достигнет только R.

Эта проблема - что участники сети не могутне иметь глобально видимого и уникального адреса - это возможно, но раздражает, чтобы решить в теории, и возможно, но раздражает, чтобы решить на практике.Насколько я знаю, библиотека Jocaml использует IP-адреса и номера портов для уникальной и глобальной идентификации узлов в распределенной программе..

Учитывая сложности современных сетевых топологий, часто помогает разделить проблему на две части: заставить машины общаться друг с другом и фактически запустить распределенную программу.Вторая часть - это то, что вы делаете, когда программируете в JoCaml.Для первой части ssh - инструмент выбора.Выберите одну машину или одну область сети (Интернет или интрасеть) в качестве домена, в котором будет работать ваша программа, и подключите каждую машину за пределами этого домена к машине в домене с туннелем SSH.Этот подход подходит не для всех случаев использования: связь между двумя компьютерами за пределами домена будет проходить через домен, что может быть проблемой производительности и надежности.Чтобы выйти за рамки этого, вам нужно либо настроить свою сеть так, чтобы у каждого участника был адрес, видимый для всех остальных участников (что вы можете или не можете сделать, в зависимости от того, что вам разрешено делать назадействованы роутеры);или реализовать неглобальную модель адресов для JoCaml (которая была бы интересной и полезной, но требует больших усилий).

0 голосов
/ 06 марта 2011

Используя

Unix.ADDR_INET(server_addr.Unix.h_addr_list.(0), 12345)

, вы сообщаете системе, что хотите, чтобы порт был связан только с локальным интерфейсом обратной связи.Это специальное виртуальное сетевое устройство, которое можно использовать для быстрой локальной связи.

Скорее используйте

Unix.ADDR_INET (Unix.inet_addr_of_string "0.0.0.0", 12345)

для прослушивания на любом сетевом интерфейсе вашей машины.Таким образом, ваш сервер будет принимать соединения и от реальных сетевых интерфейсов.

...