PDA

Просмотр полной версии : Socket securityError :: Error #2048


Eric Gurt
15.10.2010, 22:37
Всем добрый вечер :)

Когда я запускаю флэшку в IDE, все работает замечательно, но при запуске из браузера Socket выдает ошибку...

Для создания подключения в коде флэшки as3:
var MP_SERVER_IP:String="91.200.106.130";
var MP_SERVER_PORT:int=10014;
var MP_socket:Socket = new Socket();

Security.loadPolicyFile("http://"+MP_SERVER_IP+"/crossdomain.xml");

MP_socket.connect(MP_SERVER_IP, MP_SERVER_PORT);

Когда флэшка делает попытку подключиться и взять кросдомэин, в логах сервера следующее:
-= Server =-

New client connected: 91.200.106.130 (Total 1 clients)
-- Client said: <policy-file-request/>�
client requested crossdomain.xml sending...
-- Client said:
client disconnected.


И спустя 5-10 секунд после попытки подключиться, прослушиватель подключения сокета сообщает securityError:
[SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]

Вот такой полный код php-скрипта, запускающего сервер:
<?

header('Content-Type: text/plain;');
error_reporting(E_ALL ^ E_WARNING);
set_time_limit(0);
ob_implicit_flush();
ob_end_flush();


echo "-= Server =-\n\n";

include("adm.php");
$address = '0.0.0.0';
$port = 10014;
$max_clients = 128;

$crossdomain = '<cross-domain-policy><allow-access-from domain="*" secure="false" to-ports="'.$port.'"/></cross-domain-policy>';


$trrr=0;

// create a streaming socket, of type TCP/IP
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

// set the option to reuse the port
socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);

// "bind" the socket to the address to "localhost", on port $port
// so this means that all connections on this port are now our resposibility to send/recv data, disconnect, etc..
// socket_bind($sock, 0, $port);
socket_bind($sock, $address, $port) or die('Could not bind to address');

// start listen for connections
socket_listen($sock);

// create a list of all the clients that will be connected to us..
// add the listening socket to this list
$clients = array($sock);

while (true)
{
@ob_flush();
// create a copy, so $clients doesn't get modified by socket_select()
$read = $clients;

// get a list of all the clients that have data to be read from
// if there are no clients with data, go to next iteration
if (socket_select($read, $write = NULL, $except = NULL, 0) < 1)
continue;

// check if there is a client trying to connect
if (in_array($sock, $read))
{
// accept the client, and add him to the $clients array
$clients[] = $newsock = socket_accept($sock);

// send the client a welcome message
//socket_write($newsock, "no noobs, but ill make an exception :)\n"."There are ".(count($clients) - 1)." client(s) connected to the server\n");
socket_write($newsock, $crossdomain, strlen($crossdomain));

socket_write($newsock, $crossdomain, strlen($crossdomain));

socket_getpeername($newsock, $ip);
echo "New client connected: {$ip} (Total ".(count($clients) - 1)." clients)\n";

// remove the listening socket from the clients-with-data array
$key = array_search($sock, $read);
unset($read[$key]);
}

// loop through all the clients that have data to read from
foreach ($read as $read_sock)
{
if (false === ($data = socket_read($read_sock, 1024)))
{
echo 'socket_read() failed: '.socket_strerror(socket_last_error())."\n";
}


echo ' -- Client said: '.$data."\n";


// check if the client is disconnected

//echo ;
if (strlen($data)==0 && ord($data)==0)
//if ($data=='')
{
// remove client for $clients array
$key = array_search($read_sock, $clients);
unset($clients[$key]);
echo "client disconnected.\n";
// continue to the next client to read from, if any
continue;
}


// trim off the trailing/beginning white spaces

$data = trim($data);

//if ($data == '<policy-file-request/>')
if (substr($data, 0, 12) == substr('<policy-file-request/>', 0, 12))
{
echo "client requested crossdomain.xml sending...\n";

socket_write($send_sock, $crossdomain, strlen($crossdomain));
}
else
{
$ans='Beep';

echo 'Sending "'.$ans.'"'."\n";
socket_write($send_sock, $ans, strlen($ans));
//$data=$ans;
//$trrr++;
}
// check if there is any data after trimming off the spaces
if (!empty($data))
{

// send this to all the clients in the $clients array (except the first one, which is a listening socket)
foreach ($clients as $send_sock)
{

// if its the listening sock or the client that we got the message from, go to the next one in the list
if ($send_sock == $sock || $send_sock == $read_sock)
// continue;

// write the message to the client -- add a newline character to the end of the message
socket_write($send_sock, $data."\n");

} // end of broadcast foreach

}

} // end of reading foreach
}

// close the listening socket
socket_close($sock);
?>

Как сервер использую Ubuntu, ipv6 выключен. Мало чего соображаю в серверах и программировании сокетов, но кажется что все верно... Почему тогда может не работать?

chabapok
16.10.2010, 01:37
кроссдомейн оно просит по 443 порту, а если там нет, то у сокета. вроде так.
и еще у XMLSocket строки нуль-треминированные, не работает у вас поэтому, наверное.

Добавлено через 3 минуты
сорри, у вас Socket, а не XMLSocket.
попоробуйте флюшить его после записи в него кроссдомейна.

gloomyBrain
16.10.2010, 04:44
Внимательно читаем и ищем отличия:

Security.loadPolicyFile("xmlsocket://foo.com:414");



просит по 443 порту

По 843


попоробуйте флюшить его после записи в него кроссдомейна

Да, это желательно, но не обязательно, т.к. единственное, что нужно сделать - это отдать файл и закрыть сокет

Eric Gurt
16.10.2010, 11:24
попоробуйте флюшить его после записи в него кроссдомейна.
мм а как именно это можно сделать? :confused:
Попробовал вставить MP_socket.flush(); после Security.loadPolicyFile("http://"+MP_SERVER_IP+"/crossdomain.xml"); выдало ошибку, попробовал после MP_socket.connect(MP_SERVER_IP, MP_SERVER_PORT); и тоже выдало ошибку, и среди PHP функций для работы с socket'ами flush ф-ций тоже не нашел:(

2gloomyBrain вроде бы файл запрашивается правильно (или нет?), но flash на него никак не реагирует

chabapok
16.10.2010, 13:22
нет, флюшить его надо на той стороне, которая отдает контент, после отдачи контента.
это если вы после отдачи контента не закрываете соединение. Если закрываете - оно автоматом отфлюшиться должно.

gloomyBrain
16.10.2010, 14:53
роде бы файл запрашивается правильно (или нет?)

Вроде бы xmlsocket:// это не http:// (или нет?)

Eric Gurt
16.10.2010, 16:12
нет, флюшить его надо на той стороне, которая отдает контент, после отдачи контента.
это если вы после отдачи контента не закрываете соединение. Если закрываете - оно автоматом отфлюшиться должно.

После отдачи crossdomain'а, флэшем похоже шлется нулевой байт и сервер соединение закрывает, как видно из лога... а flush разве используется еще для чего-то кроме вывода в браузер части страинцы, или есть еще фунуции flush для сокетов? (я не смог найти по этой теме ничего). После socket_write($send_sock, $crossdomain, strlen($crossdomain)); Поставил flush(); и @ob_flush(); на всякий случай, в итоге никаких изменений.

Вроде бы xmlsocket:// это не http://
заменил
Security.loadPolicyFile("http://"+MP_SERVER_IP+"/crossdomain.xml"); на Security.loadPolicyFile("xmlsocket://"+MP_SERVER_IP+":"+MP_SERVER_PORT);
теперь флэшка нулевой байт не шлет и не отключается до закрытия всей страницы с флэшкой. в логе
New client connected: 91.200.106.130 (Total 1 clients)
-- Client said: <policy-file-request/>�
client requested crossdomain.xml sending...

chabapok
16.10.2010, 18:37
вы путаете понятия нулевой байт с...даже не знаю как это назвать.
Вобщем, нулевой байт - это байт с кодом ноль �. У вас в логе он расположен самым последним символом, сразу после "<policy-file-request/>" в той же строке.
А вторая надпись в логе " -- Client said:" -- это никакой не нулевой байт, это вообще не байт, там пустой буфер. Если вы там сделаете echo strlen($data), то получите 0.

А если вы еще и распечатете там часики, то увидите, что клиент дропает сокет не сразу, а по истечении таймаута.

это наводит на мысль, что можно попытаться отдавать полиси нуль-терминированным. Попробуйте.
то есть после присвоения прицепляете в конец ноль:
$crossdomain .= "\0";
и потом уже с ним работаете. c XMLSocket только так и работает.

кстати, у вас кроссдомейн странный.
нате вам мой, с уже прцепленным нулем:
$xmlpolicy="<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"$port\" /></cross-domain-policy>\0";

так, тут его форум маленечко обрезает... вобщем перед каждой двойной кавычкой, которая должны пойти в контент, ставите обратный слешь. То есть после version= идет обратный слешь, а только потом кавычка.

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

Eric Gurt
16.10.2010, 19:52
При запуске флэшки из браузера с debug версией флэша, спустя 15 секунд после подключения:
Connection securityError: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Нарушение изолированной среды: http://91.200.106.130/xxx.swf?36072 не может загрузить данные из 91.200.106.130:10014."]

При запуске из IDE все так же хорошо.

В логе все происходит в одну секунду, после "<policy-file-request/>" флэшка сразу шлет пустой буффер:
[07:16:43] New client connected: 91.200.106.130 (Total 1 clients)
[07:16:43] -- Client said: <policy-file-request/>�
[07:16:43] client requested crossdomain.xml sending...
[07:16:43] -- Client said:
[07:16:43] client disconnected.

из-за которого, как видно далее, сервер её отключает (это верно?)
Код сервера:


...

$address = '0.0.0.0';
$port = 10014;

$crossdomain="<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"$port\" /></cross-domain-policy>\0";

...

if (strlen($data)==0 && ord($data)==0)
// так было в одном из примеров, с которого все началось
// сервер отключается при получении пустого буфера
{
// remove client for $clients array
$key = array_search($read_sock, $clients);
unset($clients[$key]);
echo date("[H:i:s] ")."client disconnected.\n";
// continue to the next client to read from, if any
continue;
}


if (substr($data, 0, 12) == substr('<policy-file-request/>', 0, 12))
// отправка policy
{
echo date("[H:i:s] ")."client requested crossdomain.xml sending...\n";
socket_write($send_sock, $crossdomain, strlen($crossdomain));
}

...



"xmlsocket://" вообще корректно использовать при Socket?
Security.loadPolicyFile("xmlsocket://"+MP_SERVER_IP+":"+MP_SERVER_PORT);

PS: пробовал убрать из php скрипта отключение при получении пустого буфера (почему он приходит?), и тогда флэшка шлет их тысячами после запроса полиции. Может это что-то значит?

gloomyBrain
16.10.2010, 21:11
"xmlsocket://" вообще корректно использовать при Socket?

Да - это протокол для загрузки файлов политики безопасности.


(почему он приходит?) Может это что-то значит?

Это значит что связь прервалась. Т.е. флешка отключилась по собственной инициативе. Так и должно быть.
После отключения флешка должна подключиться заново. Если этого не происходит - значит Вы отдаете некорректный policy файл.

Eric Gurt
16.10.2010, 22:28
и после отключения флэшка еще долго думает перед тем как сообщить ошибку, не говоря уже о том, что при Security.loadPolicyFile("xmlsocket://"+MP_SERVER_IP+":"+MP_SERVER_PORT); в логах сервера вообще ничего не появляется нового. бред какой-то

если это о чем-то скажет - то тестовую флэшку можно увидеть здесь:
http://91.200.106.130/pb2/socket_test.swf
Если http://91.200.106.130 грузится (значит мой компьютер с сервером включен), то по идее и кнопка CONNECT должна работать, но она работает только через IDE. у меня в браузерах - нет.

Добавлено через 24 минуты
Ошибка: [строгий] Игнорирование файла политики на xmlsocket://91.200.106.130:10014 из-за неправильного синтаксиса. Сведения об устранении этой проблемы см. на веб-сайте http://www.adobe.com/go/strict_policy_files_ru.

вот в чем дело. похоже осталось только перевести и понять этот (http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html) текст

Добавлено через 1 час 42 минуты
ничего не пойму... все же правильно вроде :confused:

chabapok
17.10.2010, 01:05
да вроде все правильно -- я давал кроссдомейн из рабочего примера! Правда у меня был XMLSocket, но это не должно играть роли.
Может быть, Socket-у как раз нуль-терминированной строки не нравятся, в отличии от XMLSocket-а... Фиг его знает.

я еще заметил, у вас адрес устанавливается $address = '0.0.0.0';
попробуйте, что ли айпишник туда свой внешний поставить.

Я не уверен, что вы сделали правильно, засветив свой внешний ip -- его могут роботы увидеть и что-то нехорошее вам слать. Надо адреса шифровать, типа как я это сделал ниже.

вобщем. Остюда 78.iii.21 точка 150 двоеточие 10000 слешь sock.php1 заменяете буквы i на едницу и скачиваете (если у меня комп включен) пример, который работает, правда, с XMLSocket. Вам только нужно будет свой адрес и порт поставить. Попробуйте не 0.0.0.0, а вписать туда свой внешний. О результатах доложите.

И попробуйте не делать во флешке Security.loadPolicyFile, так как флеш автоматом должна запросить его.

Eric Gurt
17.10.2010, 01:52
chabapok, Ваш сервер работает на ура! :yahoo:
подменил адрес с портом (на "0.0.0.0" и 10014) и все заработало с первого раза!
еще до конца не понял в чем дело, но похоже дело было все-таки в серверной части :)

Спасибо огромное за помощь еще раз :)

xidived
10.02.2013, 03:51
Какой в итоге должен быть код нормально работающего PHP сервера? Скиньте пожалуйста если есть у кого-то.

KumoKairo
10.02.2013, 12:05
Я помню мы тоже долго мучились с этим кросдомейном, оказалось, что нужно выключить использование IPv6 на сервере

xidived
10.02.2013, 17:27
Проблема полностью идентична с авторской. Судя по посту автор написал что проблема в серверной части. Но в чем именно не понятно. Знает кто решение?

iflamberg
11.02.2013, 13:27
Плюсую gloomyBrain. После запроса файла политик сокет себя отключает и если с файлом политик все ок - пподключает заново.