Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > Переслать код от клиента серверу


Автор: DoZENT 7.3.2009, 20:14
Привет всем! Передо мной встала несколько необычная проблема: мне необходимо переслать произвольный код (функцию с заранее неизвестным количеством аргументов) от клиента серверу и выполнить его на сервере. Куда копать и вообще возможно ли это? Заранее спасибо.

Автор: vinick 7.3.2009, 22:43
Зачем что-то копать? Надо просто переслать код серверу, он подгготовит его к выполнению, потом переслать аргументы, сервер передаст полученные аргументы в функцию и вернет результат. Только договоритесь с сервером о протоколе и все дела. 

Только зачем  это надо. Очень похоже на попытку сделать большую кнопку с надписью "Сдалать все."

Автор: neosapient 8.3.2009, 16:40
как вариант, перешли DLL и запусти на целевой машине

Автор: DoZENT 8.3.2009, 18:41
Цитата(vinick @  7.3.2009,  22:43 Найти цитируемый пост)
Надо просто переслать код серверу, он подгготовит его к выполнению, потом переслать аргументы, сервер передаст полученные аргументы в функцию и вернет результат

Вы сейчас просто переписали мой вопрос. КАК это сделать? Желательно кроссплатформенно.

Добавлено через 3 минуты и 44 секунды
Цитата(neosapient @  8.3.2009,  16:40 Найти цитируемый пост)
как вариант, перешли DLL и запусти на целевой машине 

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

Автор: DoZENT 8.3.2009, 19:26
если оформить функцию как новый тип:

Код

typedef void(*MyFunc)(int a);


и писать в сокет переменную этого типа, то на сервер передастся сама функция или только ее адрес?

Автор: vinick 8.3.2009, 22:39
Цитата(DoZENT @  8.3.2009,  18:41 Найти цитируемый пост)
Вы сейчас просто переписали мой вопрос. КАК это сделать? Желательно кроссплатформенно.

В правильном вопросе содержится половина ответа.

1. Переслать текстовый файл с кодом
2. Запустить на сервере компилятор и собрать динамическую библиотеку
3. Загрузить библиотеку в процесс сервера
4. Передать на сервер параметры 
5. Передать параметры в функцию
6. Выполнить код.

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

Параметры в функцию можно передавать через массив указателей на void, функция внутри себя сама сможет разобрать этот массив. А можно прямо на клиенте серилизовать этот массив (посмотри на boost.serialization) и передавать его таким по сети, а функция опять же внутри себя сможет восстановить параметры и таким же образом вернуть результат. В обоих случаях прототип вызываемой функции будет всегда один и тот же и серверу не потребуются лишние знания.

Еще можно писать функции на скриптовом языке, а в сервер встроить интерпретатор этого языка. Можно вобще переписать сервер на языке поддерживающем инструкцию eval. 

вариант со скриптами на мой взгляд самый кросс-платформенный.


Цитата(DoZENT @  8.3.2009,  19:26 Найти цитируемый пост)
и писать в сокет переменную этого типа, то на сервер передастся сама функция или только ее адрес?

Только адрес, который на другой машине не будет иметь никакого смысла.

Автор: 0xDX 9.3.2009, 06:53
во первых DLL это не есть хорошо(в данном случае).
во вторых правильно поставденный вопрос 50% ответа.

Но автора пора научить плохому(плохому так как это хакерский трюк)
shell-code - почитай.


А вообще можно использовать что то типа COM(от мелкомягких), CORBA........

Можеш. взять интерпретатор(типа встроенного в QT, но лучше мозиловский, так как не как а ява скрипт это стандарт.....)
Или LUA, и пересылать уже текст на этой программе. Можешь есче покопать в rpc.

Вообщем смотри сам, у кого какая задача, и каждый решает задачу по своему.....

Автор: Lazin 9.3.2009, 12:03
ИМХО, бред и дыра в безопастности...
во первых, как можно вызвать то, что ты не знаешь как вызывать, если ты не знаешь что передавать в функцию, то ты не можешь эту ф-ю вызвать.
во вторых, если даже ф-ии имееют всегда один и тот-же набор параметров, кроссплатформенным это не будет, тебе придется передавать dll динамичесски загружать ее.
если использовать скрипты, то все-равно это дыра... злоумышленник может передать твоему приложению специально подготовленный скрипт и получить доступ к компьютеру.

Автор: DoZENT 9.3.2009, 12:10
Цитата(vinick @  8.3.2009,  22:39 Найти цитируемый пост)
1. Переслать текстовый файл с кодом
2. Запустить на сервере компилятор и собрать динамическую библиотеку
3. Загрузить библиотеку в процесс сервера
4. Передать на сервер параметры 
5. Передать параметры в функцию
6. Выполнить код.

понятно smile проще dll на сервер скопирую. а вот по пункту 4 есть непонятки. Как эти параметры-то передать на сервер, учитывая, что эти параметры у каждой функции свои (разное количество, тип)? Пока только смутно вижу такой вариант: прототип функции делать что-то типа 
Код
void myfunc (va_list argList)
, на сервере обрабатывать массив из аргументов. Но вообще не представляю как это реализоват на практике. smile 

Автор: neosapient 9.3.2009, 12:17
Я б передал параметры в виде текста, так как распарсить строчку с текстом легко. В общем смысле это будет xml-теги.
Второй вариант, передать вместе с dll (или по раздельности) файл инициализации/конфигурации.


Автор: DoZENT 9.3.2009, 14:50
Цитата(neosapient @  9.3.2009,  12:17 Найти цитируемый пост)
Я б передал параметры в виде текста, так как распарсить строчку с текстом легко. В общем смысле это будет xml-теги.Второй вариант, передать вместе с dll (или по раздельности) файл инициализации/конфигурации.

хороший вариант при жестко ограниченном количестве допустимых типов агрументов. Т.е., например строка с параметрами будет выглядеть так: 
Код
@int i=0, QString str="somestring"@
 В этом случае пропарсить проще простого. А вот если пользователю захочется сделать одним из параметров нестандартный тип? Например, свою какую-то структуру? Здесь такой вариант не подходит. Чувствую, надо использовать что-то типа va_list, va_arg, и т.д., только вот не знаю как это применить к моей задаче.

Автор: neosapient 9.3.2009, 15:09
Цитата(DoZENT @  9.3.2009,  14:50 Найти цитируемый пост)
А вот если пользователю захочется сделать одним из параметров нестандартный тип?

В этом случае и надо использовать xml, ну на худой конец JSON (http://json.org/)

Автор: vinick 9.3.2009, 15:27
Цитата(DoZENT @  9.3.2009,  12:10 Найти цитируемый пост)
Как эти параметры-то передать на сервер, учитывая, что эти параметры у каждой функции свои (разное количество, тип)? 

Почитай что такое сериализация. Я так понимаю ты используешь Qt, там вроде должно быть что-то подобное. Можешь посмотреть boost.serialization, если не хочешь тянуть буст, можно по образу и подобию сделать свой вариант, я так делал - это не сложно.

c применением буста это будет выглядеть примерно так 
Пусть функции требуется структура MyStruct, int  и double
Код

// Описание пользовательских структур
struct MyStruct
{
   int a;
   double b;
   std::string s;
   template<typename Archive>
   void serialize(Archive &ar, const unsigned int version) 
   {
        ar &  a & b & s;
    }
};


Код

// код клиента
std::ostringstream os;
boost::archive::text_oarchive oar(os);
MyStruct ms;
int param1;
double param2;
// Заполняем поля ms и инициализируем параметры param 1
// ...

oar <<  ms << param1 << param2;
SendToMyServer(os.str()); // отправляем параметры на сервер


Код

// код сервера
std::string s = ReadStringFromClient();
DLLFunction(s)l; // вызываем функцию из DLL


Код

// код в DLL
DLLFunction(const std::string &s)
{
    std::istringstream is(s);
    boost::archive::text_iarchive iar(is);
    MyStruct ms;
    int param1;
    double param2;
    iar >> ms >> param1 >> param2;
   // Дальше работаем с нужными параметрами.
}


Автор: DoZENT 9.3.2009, 16:27
Цитата(Lazin @  9.3.2009,  12:03 Найти цитируемый пост)
ИМХО, бред и дыра в безопастности...

безопасность - отдельная тема, я потом вас с ней замучаю  smile 
Цитата(Lazin @  9.3.2009,  12:03 Найти цитируемый пост)
во первых, как можно вызвать то, что ты не знаешь как вызывать, если ты не знаешь что передавать в функцию, то ты не можешь эту ф-ю вызвать.

вот я и спрашивал, возможно ли это? оказалось, что без извратов - нет, поэтому 
Цитата(Lazin @  9.3.2009,  12:03 Найти цитируемый пост)
тебе придется передавать dll динамичесски загружать ее.


Цитата(Lazin @  9.3.2009,  12:03 Найти цитируемый пост)
кроссплатформенным это не будет

QT сервер, QT либа, все ОК =)

Добавлено через 8 минут и 47 секунд
vinick, вот за сериализацию спасибо! Как-то не подумал про нее. В QT для этого QDataStream. Только вот клиента разрабатывать другая фирма будет, придется им QT что-ли навязывать.. Ну это уже мелочи) Спасибо!

Автор: Lazin 9.3.2009, 16:52
Цитата(DoZENT @  9.3.2009,  16:27 Найти цитируемый пост)
QT сервер, QT либа, все ОК =)

сервер работает под linux, клиент под мак, и что дальше? smile 

Автор: DoZENT 9.3.2009, 17:01
Цитата(Lazin @ 9.3.2009,  16:52)
Цитата(DoZENT @  9.3.2009,  16:27 Найти цитируемый пост)
QT сервер, QT либа, все ОК =)

сервер работает под linux, клиент под мак, и что дальше? smile

компилируем либу под linux и шлем на скомпилированный под linux сервер

Автор: Lazin 9.3.2009, 17:41
IMO - скорее всего проблема должна решаться проще =)

Автор: DoZENT 9.3.2009, 18:15
Куда же проще? Под конкретную ОС - конкретную версию либы. Проще только у Java, когда перекомпилировать не надо  smile 

Автор: Lazin 9.3.2009, 21:30
проще - поставлять вместе с приложением все необходимые библиотеки(и предусмотреть механихм их обновления), а клиенту передавать не код функции, а информацию о том, какую ф-ю нужно вызвать(из тех, что у него уже есть) и параметры для вызова, либо информацию о том, что ему нужно обновиться

Автор: kolobok0 16.3.2009, 18:36
Цитата(Lazin @ 9.3.2009,  21:30)
проще - поставлять вместе с приложением 

апсолютно верное решение.

2 DoZENT
Либо смотрите в сторону явы, си бимоля и иже...
либо рисуйте свой аля шарп..

по поводу передать "конкретную либу" - хотел бы я услышать Ваш мат, когда патч пройдёт по серверу и функция Z перестанет дышать..почему-то smile

привязываться к железу либо ОС - большая глупость...

удачи Вам, она Вам потребуется...
(круглый)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)