Просмотр полной версии : Сервер на С++, клиент на Flash. Файл политики
Casperovskii
01.03.2013, 22:31
Привет всем! Сижу уже целый день на одном месте, пишу в QT свой код. Есть такая проблема, флеш коннектится по 843 порту, ему уходит строчка с файлом политики сокетов, но он (флеш) не воспринимает его. Перечитал здесь темы 3-4, но так и не осилил. Почитал статью на хабре, не помогло. В общем сейчас вы - моя последняя надежда.
Код на С++:
if (txt==QString("<policy-file-request/>")){
const char *line="<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";
qDebug()<<line;
socket->write(line);
На флеше просто коннект по 1234 порту. Сокет объявлен выше вот так:
socket = new QTcpSocket();
Ошибка, которую выдает флеш имеет такой вид:
Error #2048: Нарушение изолированной среды:
и т.д.
Вижу точно одну ошибку и одну потенциальную ошибку.
Точно ошибка в том, что вы нулевой байт не посылаете в конце сообщения. char * не может содержать нулевого байта по определению. Это байт-терминатор. Так что все, что работает с этим char * (без явного указания длины) не воспринимает ваш \0 как часть строки. Поставьте \0 в начале и наслаждайтесь debug(). Как правильно сделать - не скажу, не пишу на С++ и документацию лень искать. Наверное, где-то в ней должно быть написано, как отдельные байты посылать.
Потенциальная ошибка. char != byte. А вот flash-player, вероятно, ждет все в UTF-8 (не проверял, может быть, заголовок xml корректно понимает). В какой кодировке socket->write пишет? А вдруг там utf-16? Или этот write ожидает byte */void * (и пишет байты) а при этом у вас char 16-битный или даже 32-битный? По-хорошему, нужно либо сразу работать с байтами, либо кодировать/декодировать текстовую строку в правильный байтовый буфер.
Если используете Qt 5 - откатывайтесь скорей на Qt 4.8.4.
В пятерке пока многова-то ошибок.
И для перевода всего в UTF-8:
QTextCodec *utfcodec=QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForTr(utfcodec);
QTextCodec::setCodecForCStrings(utfcodec);
Как разберетесь - отпишитесь.
Удачи!
Casperovskii
03.03.2013, 12:58
Да, верно, программирую в QT, только 4.8.
Сейчас попробовал сделать вот так:
if (txt==QString("<policy-file-request/>")){
QByteArray line=QString("<cross-domain-policy> <allow-access-from domain=\"*\" to-ports=\"*\"/> </cross-domain-policy>").toUtf8();
qDebug()<<line;
socket->write(line+"\0");
}
Сделал через qDebug вывод текущих действий и вот что получается:
843port
"<policy-file-request/>"
"<cross-domain-policy> <allow-access-from domain="*" to-ports="*"/> </cross-domain-policy>"
other port
"<policy-file-request/>"
"<cross-domain-policy> <allow-access-from domain="*" to-ports="*"/> </cross-domain-policy>"
Т.е. Flash так и не распознал в этой строке фаил политики. Строку преобразовал в объект QByteArray, и добавляю нулевой байт непосредственно во write.
Что еще можно попытаться сделать?
Так... С кодировками стало гораздо лучше. Только вот вы зачем-то к буферу прибавляете пустую строку. Это нехорошо. Это ничего не даст. Прибавляйте к ней char, тогда он добавится. Или, лучше, append'ите char в этот буфер, а не прибавляйте. Должно помочь.
Casperovskii
03.03.2013, 16:46
if (txt==QString("<policy-file-request/>")){
QByteArray line=QString("<cross-domain-policy> <allow-access-from domain=\"*\" to-ports=\"*\"/> </cross-domain-policy>").toUtf8();
line.append("\0");
qDebug()<<line;
socket->write(line);
}
Не помогло. Или я неправильный нулевой байт добавляю?
Неправильно. Вы опять добавляете строку (char *, пустую), а я прошу добавить символ (char). Ладно, подскажу. Символ записывается '\0'.
KumoKairo
03.03.2013, 19:15
Не забудьте отключить IPv6 на сервере.
Casperovskii
03.03.2013, 20:51
Символ записывается '\0'.
Именно оно! Да! Все заработало. Окончательный код сервера:
if (txt==QString("<policy-file-request/>")){
QByteArray line=QString("<cross-domain-policy> <allow-access-from domain=\"*\" to-ports=\"*\"/> </cross-domain-policy>").toUtf8();
line.append('\0');
qDebug()<<line;
socket->write(line);
}
Огромное спасибо! Вдохнул в меня жизнь просто.
iflamberg
03.03.2013, 20:57
Вот странно, кстати, у меня вот так работает:
char* securityAnswer =
"<cross-domain-policy>"
"<allow-access-from domain=\"*\" to-ports=\"3425\" />"
"</cross-domain-policy>";
...
send(c.sock, securityAnswer, strlen(securityAnswer), 0);
close(c.sock);
без всяких '\0'.
Casperovskii
17.04.2013, 00:46
Всем привет! У меня очередная проблема, боролся месяц, сам не смог победить. Хабр, друзья и другой форум не помогли :(. Итак, у меня есть во Flash:
public function dataWrite(e:Event):void {
clientSocket.writeUTFBytes(fieldToWrite.text);//сокет, подключенный к серву на QT
clientSocket.flush();
trace(clientSocket.bytesAvailable, clientSocket.connected);
fieldToWrite.text = "";//текстовое поле, из которого берем строку для передачи
fieldToWrite.setFocus();
}
И код функции на сервере, которая должна срабатывать каждый раз, когда любой из клиентов посылает строчку:
void multiServer::sendDataToForm(int socDesc, QString txt)
{
qDebug()<<listOfThreads.size(); //листстредов - всех клиентов, выводим его размер
qDebug()<<txt;//считанный с любого из клиентов текст
QString txt2 = QString::number(socDesc) + ";" + txt;
emit sendingData(MainWindow::DATAINCOME,txt2);//отправляем считанный текст в гуи
for (int i = 0;i<listOfThreads.size();i++) //цикл отправки всем клиентам сообщения
{
QByteArray myByteArray;
//отправляем
listOfThreads[i]->socket->write(myByteArray.append(QString("Client written;") + QString::number(socDesc) + ";" + txt));
qDebug()<<myByteArray;
}
}
Проблема в следующем: если отсутствует цикл, то сервер считывает все сообщения прекрасно, но, естественно, ничего не отсылает назад. Если цикл есть, то сервер считывает первое сообщение, отсылает его всем клиентам и больше не может считать ни одного сообщения, кроме вновь подключившегося клиента. Добавление в цикл для сокета функций waitforreadyread() и flush() не помогло. Прошу вашей помощи. Спасибо за внимание.
P.S. Если нужен другой код (объявление треда или код самого треда и так далее, готов предоставить. Но проблема именно в цикле/отправке данных обратно на клиент).
Нужен совет :) тоже в тему С++ и файл политик
Есть клиент который лежит на 80 порту
Есть сервер который лежит на 7777 порту (который не может отдавать файл политик)
Есть программка на 1111 порту, которая выполняет функцию моста между сервером-клиентом. В которой банально:
if (str=="<policy-file-request/>")
return "<cross-domain-policy>...</cross-domain-policy>";
else
//ломится на сервер с портом 7777 и возвращает результат
Вопрос: пройдет ли такая штука?
Если да, интересуют сроки и стоимость такой программы на С++...
caseyryan
22.04.2013, 13:09
нет. Файл политик флеш плеер по умолчанию будет запрашивать с 843 порта. И сервер должен отдавать его именно с этого порта.
то есть хотите сказать при связке
клиент > программа на 1111 порта > сервер на 7777 порту
клиент запросит файловую политику с 7777?
то есть хотите сказать при связке
клиент > программа на 1111 порта > сервер на 7777 порту
клиент запросит файловую политику с 7777?
Можно явно указать, откуда запрашивать policy:
public function get PolicyServer():String
{
return "xmlsocket://" + Host + ":" + PolicyPort;
}
...
Security.loadPolicyFile(PolicyServer);
caseyryan
22.04.2013, 21:32
то есть хотите сказать при связке
клиент > программа на 1111 порта > сервер на 7777 порту
клиент запросит файловую политику с 7777?
Похоже я вообще не понял Вашего вопроса
Можно явно указать, откуда запрашивать policy:
public function get PolicyServer():String
{
return "xmlsocket://" + Host + ":" + PolicyPort;
}
...
Security.loadPolicyFile(PolicyServer);
То есть я могу работать с сервером, который запущен на 7777, а файловую политику для него брать с 1111?
Я так и делаю, вручную получаю политику, через Security.loadPolicyFile, но полагал что ip: port необходимо прописывать именного того сервака, к которому впоследствии обращаюсь
caseyryan
23.04.2013, 13:55
В общем, да. Получается такая схема. Флеш плеер стучится на указанный порт для получения файла политик. Получает этот файл и закрывает соединение. Все. Он убедился что ресурс разрешает ему доступ и теперь может коннектиться на любой другой порт. Так и должно быть, это нормально.
но полагал что ip: port необходимо
ip - да
порт - нет
ip - да
порт - нет
Спасибо это как раз то что мне нужно.
caseyryan
23.04.2013, 18:48
Всем привет! У меня очередная проблема, боролся месяц, сам не смог победить. Хабр, друзья и другой форум не помогли :(. Итак, у меня есть во Flash:
public function dataWrite(e:Event):void {
clientSocket.writeUTFBytes(fieldToWrite.text);//сокет, подключенный к серву на QT
clientSocket.flush();
trace(clientSocket.bytesAvailable, clientSocket.connected);
fieldToWrite.text = "";//текстовое поле, из которого берем строку для передачи
fieldToWrite.setFocus();
}
И код функции на сервере, которая должна срабатывать каждый раз, когда любой из клиентов посылает строчку:
void multiServer::sendDataToForm(int socDesc, QString txt)
{
qDebug()<<listOfThreads.size(); //листстредов - всех клиентов, выводим его размер
qDebug()<<txt;//считанный с любого из клиентов текст
QString txt2 = QString::number(socDesc) + ";" + txt;
emit sendingData(MainWindow::DATAINCOME,txt2);//отправляем считанный текст в гуи
for (int i = 0;i<listOfThreads.size();i++) //цикл отправки всем клиентам сообщения
{
QByteArray myByteArray;
//отправляем
listOfThreads[i]->socket->write(myByteArray.append(QString("Client written;") + QString::number(socDesc) + ";" + txt));
qDebug()<<myByteArray;
}
}
Проблема в следующем: если отсутствует цикл, то сервер считывает все сообщения прекрасно, но, естественно, ничего не отсылает назад. Если цикл есть, то сервер считывает первое сообщение, отсылает его всем клиентам и больше не может считать ни одного сообщения, кроме вновь подключившегося клиента. Добавление в цикл для сокета функций waitforreadyread() и flush() не помогло. Прошу вашей помощи. Спасибо за внимание.
P.S. Если нужен другой код (объявление треда или код самого треда и так далее, готов предоставить. Но проблема именно в цикле/отправке данных обратно на клиент).
А почему QByteArray myByteArray; объявлен, но не инициализирован? По логике здесь должнно быть какое-то искелючение типа NullPointerException или какой там аналог в С++.
В джаве такая конструкция бы сразу упала, без вариантов. Даже примитив так нельзя объявить в джаве без инициализации внутнри тела метода. На уровне класса можно, он примет значение по умолчанию, но внутри метода никакого умолчания не будет. Вылетит исключение. В общем, это лишь предположение, но советую проверить
А почему QByteArray myByteArray; объявлен, но не инициализирован?
Это же плюсы, так что инициализирован конструктором без аргументов, живет на стеке, будет убит при выходе из блока деструктором (если есть). С++ один из немногих языков, где значением переменной может быть не только ссылка, но и объект. А был бы C, память бы тоже была выделена, но в ней был бы мусор и программа могла бы успешно работать (если бы повезло) или не работать (если бы не повезло).
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.