Как сделать NAT с сокетами PHP

Я пытаюсь сделать одноранговое приложение в php, чтобы оно работало так же, как работает Skype. Он работает с внутренними адресами, но когда я пытаюсь отправить данные на свой внешний адрес, сообщение туда не попадает. Очевидно, мне не хватает перевода адресов, но я не понимаю, как это сделать с помощью PHP-сокетов. Является ли это возможным?

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

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));
socket_bind($socket, "0.0.0.0", 100) or die("Could not bind socket: " . socket_strerror(socket_last_error($socket)));

$ret = "";
$from_ip = "";
$from_port = 0;


echo "waiting...\n";
socket_recvfrom($socket, $ret, 6, 0, $from_ip, $from_port);

var_dump($ret, $from_ip, $from_port);

socket_close($socket);

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

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));


$to_ip = "externalip"; //works with internal "127.0.0.1";
$to_port = 100;
$message = "hello!";

socket_sendto($socket, $message, strlen($message), 0, $to_ip, $to_port);
echo "sent\n";

socket_close($socket);

Но он отправляет и выходит, но первый скрипт все еще ждет... Уже некоторое время занимаюсь этим, может ли кто-нибудь мне помочь?

-- Редактировать --

Итак, я реализовал stun-сервер и настроил для него переадресацию портов следующим образом:

<?php

echo "-- STUN SERVER --\n";

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));
socket_bind($socket, "0.0.0.0", 5104) or die("Could not bind socket: " . socket_strerror(socket_last_error($socket)));


do {
    $ret = "";
    $from = "";
    $port = 0;

    echo "waiting...\n";
    socket_recvfrom($socket, $ret, 6, 0, $from, $port);

    echo "received: $ret\n";

    $message = $from.":".$port;
    socket_sendto($socket, $message, strlen($message), 0, $from, $port);
    echo "sent: $message\n\n";
}
while (true);

и изменил мой первый скрипт, чтобы получить его ip/port с ошеломляющего сервера:

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));
socket_bind($socket, "0.0.0.0", 100) or die("Could not bind socket: " . socket_strerror(socket_last_error($socket)));

$ret = "";
$from = "";
$port = 0;


echo "sending info to stun server...\n";
$to_ip = "stunip";
$to_port = 5104;
$message = "get_ip";
socket_sendto($socket, $message, strlen($message), 0, $to_ip, $to_port);

echo "waiting for stun...\n";
$stuninfo = "";
socket_recvfrom($socket, $stuninfo, 25, 0, $from, $port);

var_dump($stuninfo); // i use this info in my second script


echo "waiting...\n";
socket_recvfrom($socket, $ret, 6, 0, $from, $port);

var_dump($ret, $from, $port);

socket_close($socket);

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


person nevernew    schedule 06.04.2014    source источник
comment
Вы ищете термин NAT traversal. Взгляните на STUN.   -  person hek2mgl    schedule 07.04.2014
comment
Ахах, кажется, я понял. Итак, в моем первом сценарии id сначала отправляет запрос на сервер, используя мой сокет, который возвращает мой общедоступный IP-адрес и порт, использованный для выполнения этого запроса, а затем я могу использовать этот IP-адрес и порт во втором сценарии? Это действительно так просто, или я пропустил еще один шаг?   -  person nevernew    schedule 07.04.2014
comment
@ hek2mgl Я реализовал ошеломляющий сервер, кажется, он отправляет мне именно то, что я ожидал, мой IP-адрес и порт 100, но затем, когда я отправляю ему сообщение из моего второго скрипта, первый по-прежнему никогда не получает это :( Можете ли вы или кто-нибудь увидеть, в чем может быть проблема, и указать мне правильное направление?   -  person nevernew    schedule 07.04.2014
comment
Эй, я был AFK некоторое время. Я никогда лично не реализовывал STUN, к сожалению, ничем помочь не могу. Я просто знал термины и оставил их здесь, чтобы указать вам правильное направление. Только с первого взгляда кажется, что вы что-то упускаете.   -  person hek2mgl    schedule 07.04.2014
comment
Я думаю, мне нужно оставить открытым соединение, к которому я подключаюсь из другого скрипта, но как я могу сделать это в PHP?   -  person nevernew    schedule 07.04.2014
comment
$to_ip = "stunip"; — поскольку stunip, очевидно, может использоваться только как заполнитель… могу я спросить, откуда вы взяли этот IP-адрес? Спрашиваю, потому что ответ на ваш вопрос вполне может быть скрыт в соответствующем разъяснении с вашей стороны.   -  person e-sushi    schedule 30.01.2015
comment
вы закончили это?? я ищу что-то подобное, помогите мне, если сможете... Спасибо   -  person Mr.Popular    schedule 30.03.2017