2010-11-11 3 views
3

Я использую Erlang для кодирования клиента bittorrent. Я застрял уже 4 дня по той же проблеме.TCP-порты в Erlang

Я посылаю рукопожатие всем сверстникам с каждым пэром, имеющим свой собственный ip: порт.

Я использую gen_tcp: connect to connect.

Проблема в том, что я не могу получить их ответ. Я провел много исследований и использовал некоторые программы для мониторинга входящих/исходящих подключений.

Одноранговые узлы получают данные и отправляют ответ обратно в порт, который я использовал для отправки им рукопожатия.

Код wise: get_tcp: connect выбирает порт и использует этот порт для отправки данных одноранговому узлу. Друг-ответ отвечает на этот порт. Однако, как вы знаете, в Erlang вам нужно использовать gen_tcp: слушать, чтобы получить ответное соединение, и вам нужно указать порт. В моем случае порт, который я должен прослушивать, это порт, который gen_tcp: connect возвращается.

Я могу получить этот номер порта, используя inet: port, но ошибка всегда одна и та же: используемый порт. Я понимаю, почему я получаю ошибку, просто потому, что порт, который я пытаюсь прослушать, уже используется gen_tcp: connect. Я попытался закрыть Socket, чтобы освободить порт, но ничего.

Итак, мой вопрос: возможно ли в Erlang подключиться к одноранговому узлу и отправить данные на него в порт, а затем прослушать этот же порт для ответа. Если нет, то я должен как-то сообщить партнеру отправить мне данные обратно на порт, который я выбираю.

Любые идеи от всех гуру Erlang приветствуются. Thanks,

// Frank.

+0

BTW Почему все недавно хотят писать bittorrent peers fpr erlang ??? –

+0

Это было задано в университете, Peer! –

ответ

6

Что-то звучит не так здесь, позвольте мне подвести итог, что вы пытаетесь сделать:

  • При использовании соединений TCP не UDP

  • соединение TCP выглядит следующим образом:

    Erlang side: IP1:Port1 <----> Peer side IP2:Port2 
    
  • IP2: Port2 - это порт, который вы передаете gen_tcp: connect, IP1 - это только IP-интерфейс вашего локального компьютера, а Port1, вероятно, является эфемерным портом выбранный стеком TCP на вашем компьютере.

  • Если равноправный ответ назад на ту же связь, вы будете получать данные как

    {tcp, Socket, Data} 
    

    сообщений как владелец порта (процесс, который, вероятно, CALLE подключения). За исключением случаев, когда вы используете пассивный режим: тогда вам нужно вызвать gen_tcp: recv og получить данные.

  • Если вы вызываете gen_tcp: вместо этого вы пытаетесь открыть другое соединение. Существуют протоколы, которые делают такие вещи, например. FTP, но вам нужно использовать другой номер порта (обычно вызывайте прослушивание, затем получите номер порта и отправьте их по существующему соединению с клиентом, который может подключиться к существующему порту). Но почти все более новые протоколы больше не делают этого с тех пор, как он беспорядочен и нуждается в брандмауэрах с сохранением состояния. Даже FTP избегает его в настоящее время. Поэтому я сильно подозреваю, что вы не хотите этого делать.

+0

BitTorrent * does * need 'gen_tcp: listen', поскольку каждый клиент также действует как сервер. Номер порта обычно определяется как конкретный, поэтому вы можете подключить отверстие в брандмауэрах и еще много чего. –

1

Bittorrent имеет два способа сверстники могут соединяться друг с другом:

  • Ваш клиент инициирует подключение к партнеру, это gen_tcp:connect. Установленное соединение является двунаправленным, и это единственное соединение - это то, что вы используете для всей связи.

  • Точка доступа соединяется с вашим клиентом. Это путь gen_tcp:listen, за которым следует gen_tcp:accept. Опять же, устанавливается двунаправленное соединение, которое вы затем используете.

Вы видите порт в использовании, вероятно, потому, что пытаетесь создать соединение «сверху» с уже имеющимся соединением. Возможно, стоит немного почитать о TCP-соединениях.

Жизнеспособный путь решения должен начинаться с предположения, что вы только подключаетесь к другим и игнорируете входящие соединения. Запуск против тестового клиента, который принимает входящие соединения и все будет работать. Затем вы можете добавлять входящие подключения к вашему коду, когда работает один из способов. Обратите внимание, что рукопожатие аналогично, но есть некоторые небольшие различия. Коннектор сначала отправляет info_hash для соединителя (например, соединитель может искать инфо-хаос среди торрентов, которые он в настоящее время обслуживает).

+0

Спасибо за ответ, я понимаю, что вы являетесь автором etorrent, если я не ошибаюсь. Я знаю, что прослушивание и подключение необходимы для протокола Bottorrent. Однако прямо сейчас все, что я пытаюсь сделать, это отправить рукопожатия и получить ответы. Поэтому я игнорирую все другие вещи. У меня также есть программа, которая показывает все подключения tcp, и она сообщает мне, что мое сообщение имеет тип рукопожатия. И сверстники на самом деле посылают мне свое рукопожатие. Но я использую gen_tcp: слушайте, чтобы получить их ответ, который, как я полагаю, сейчас не прав. Должен ли я использовать gen_tcp: recv вместо этого? – Frank

+0

EDIT, похоже, я исправил проблему. Я вернусь к тебе. Мне нужно очистить код. – Frank

+0

Прочтите сообщение «Пиерс» и изучите разницу между активными и пассивными сокетами в Erlang. Запустите 'erl -man gen_tcp'. –