• 0
Wovan2

SendCommandWithResponse

Вопросы

Здравствуйте.

Пытаюсь через Tethering получить данные с удаленного приложения. Но все реализовано через события, и при наличии нескольких клиентов у меня возникла путаница, какому клиенту, что вернуть.

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

Похожих событий на принимающей стороне  не нашел. Ведь вызвать функцию на клиенте - пол дела. Надо чтобы сервер обработал запрос и вернул результат. Или что-то не понимаю.

Может кто может хотя бы намекнуть в какую сторону искать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 ответов на этот вопрос

  • 0

Не могу найти ни одного примера использования. Даже в хелпе Delphi:huh:

Изменено пользователем Wovan2
Опечатка

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 час назад, Wovan2 сказал:

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

Там искать нечего. В глубине тетеринга эта команда - всего лишь совокупность

SendCommand(AConnection, ACommand);
Result := ReceiveCommand(AConnection);

Получается, что (как видно из названия и кода) она отправляет команду (как обычно, т.е. обработка на приеме ничем не отличается) и ждет, пока получит команду в ответ.

Единственное что - следует самому создавать TTetheringCommand со своими параметрами, а не пользоваться готовыми SendStream и SendString

Изменено пользователем kami

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

про тетеринг есть хорошее видео на ЮТ эмбаркадеро раша от Совцова

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Может, кто владеет этой технологией, подскажет как реализовать выполнение  функции на стороне сервера с возвратом результата клиенту без этого SendCommand, Другие клиенты не должны видеть друг друга и не должны перехватывать чужие данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
26 минут назад, krapotkin сказал:

про тетеринг есть хорошее видео на ЮТ эмбаркадеро раша от Совцова

Смотрел уже. Ничего нового. Все то же, что и во всем инете. Шаблонные задачи во всех источниках одинаковые: подключились, послали, в событии получили.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
29 минут назад, kami сказал:

Там искать нечего. В глубине тетеринга эта команда - всего лишь совокупность


SendCommand(AConnection, ACommand);
Result := ReceiveCommand(AConnection);

Получается, что (как видно из названия и кода) она отправляет команду (как обычно, т.е. обработка на приеме ничем не отличается) и ждет, пока получит команду в ответ.

Единственное что - следует самому создавать TTetheringCommand со своими параметрами, а не пользоваться готовыми SendStream и SendString

Не могу сообразить как обрабатывать на сервере эти команды. При вызове функции SendCommandWithResponse на клиенте, на сервере срабатывают события BeforeSendData, AfterReceiveData, BeforeSendData, AfterReceiveData, BeforeSendData, AfterReceiveData. Именно так: 3 раза парами. Параметр ADataBuffer: TByteDynArray в каждом из этих вызовов разный. Видимо в этом TByteDynArray и прячется исходная структура TTetheringCommand? Как их преобразовывать друг в друга?

Где-то надо разобрать то, что послал клиент (как-то получить посланную структуру TTetheringCommand), потом, после нужной обработки создать такую же структуру ответа и куда-то уже ее засунуть. Не могу понять где, что и куда совать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

TTetheringCommand - есть метод Create, принимающий TBytes

А вот почему 3 пары событий - это не знаю...

Изменено пользователем kami

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 03.11.2017 в 17:34, kami сказал:

TTetheringCommand - есть метод Create, принимающий TBytes

А вот почему 3 пары событий - это не знаю...

В событиях AfterReceiveData, BeforeSendData параметр имеет тип TByteDynArray. Как его в тип TBytes перевести? Туплю. Только из Delphi 7 вылез.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

На клиенте выполняю следующий код:

    LS := TStringList.Create;
    LS.Add('Привет - это я!');
    ACommand := TTetheringCommand.Create('MyCommand', 33, ['par1','par2'], LS);

    ed1.Text := 'Начало';
    try
    Resp := TAPClient.SendCommandWithResponse(TMClient.RemoteProfiles[0], ACommand);
    except
    on e:Exception do
     ShowMessage(e.Message)
    end;
    ed1.Text := 'Конец'

При выполнении всегда срабатывает исключение "Operation aborted".

На сервере в обработке TAPServerAfterReceiveData

memConnectedInfo.Lines.Add('TAPServerAfterReceiveData');
 tc := TTetheringCommand.Create(TBytes(ADataBuffer));
 try
 memConnectedInfo.Lines.Add(tc.Command);
 finally

 end;

Из нескольких срабатываниях выводится идентификатор Клиента. Хотя в Command вставляю 'MyCommand'.

Ни одного примера в во всем инете не нашел.

В 03.11.2017 в 19:12, wamaco сказал:

Эту статью тоже штудировал. Мало чем отличается по содержанию от всех остальных. Разве немного подробнее. Но TTetheringCommand нет и там.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Порядок событий на сервере


TAPServerBeforeSendData
wrWc0I8ol7
TAPServerAfterReceiveData
[пустая строка]
TAPServerBeforeSendData
{7FCD2085-28F1-4B42-9446-A73A0BC2873F}
TAPServerAfterReceiveData
{38BAA5D2-B0C3-E711-8018-AF8831B0713E}
TAPServerBeforeSendData
Error
TAPServerAfterReceiveData
[пустая строка]
TAPServerAfterReceiveData
[пустая строка]

После имени события выводится свойство TTetheringCommand.Command (как в коде выше)

Визуально похоже на обмен пакетами при сетевом общении

Сперва хеш пароля, потом обмен адресами, потом передача произвольных данных (в моем случае пустые объекты)

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

Попытка покопаться в исходных кодах ни к чему не привела. Есть интересная процедура DoOnIncomingData, но по какому событию она запускается  я не понял. Соответственно никакого события OnIncomingData у объекта TTetheringAppProfile нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

А почему не использовать TIdTCPClient/TIdTCPServer? Зачем сложности себе придумывать?
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

К Indy у меня плохое отношение. Глючные, тормозные и громоздкие компоненты. На D7 пользуюсь Synapse, не в пример проще и предсказумее. Да, я знаю, Tethering реализован на Indy (возможно с этим и связано непостоянство установки соединения). Но в данном случае хотелось попробовать саму технологию, которая везде расписана как панацея от всех сетевых проблем. А оказывается не все так просто. Только что обнаружил, что метод Connect у меня не соединяет профили (выяснил это при скурпулезной отладке на Android). Хотя в примерах Delphi все работает нормально. Буду искать где накосячил. Возможно и код приведенный выше может оказаться рабочим.

Добавлено 12:11
Товарищи. Это пипец какой-то. Если на сервере задействую события TAPServerBeforeSendData или TAPServerAfterReceiveData, клиент перестает подключаться к профилю сервера. Без этих событий все нормально подключается.

Изменено пользователем Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Кое-что прояснилось при ближайшем рассмотрении. События TAPServerBeforeSendData иTAPServerAfterReceiveData по сути функции. И результат этих функций нужно обязательно переопределять Result := ADataBuffer. При этом, видимо, можно что-то поправить в команде, принимаемой или отсылаемой. Событие TAPServerAfterReceiveData на сервере срабатывает периодически, возможно по какому-то таймауту, с пустой командой.

Кстати среди всех этих событий мне удалось выловить и свою отправленную с клиента команду 'MyCommand'. Осталось обработать ее персонально.:)

Изменено пользователем Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

И снова здравствуйте. Хотя и разговариваю сам с собой, но все же, может кто еще и откликнется.

В общем продолжаю мучить Tethering. В событии TAPServerAfterReceiveData удалось перехватить отправленную моим клиентом команду.

Но дальше пока не пошло. Навскидку имеется две проблемы.

Первая. Клиент передает команду на сервер так:

LS := TStringList.Create;
LS.Add('Привет - это я!');          
ACommand := TTetheringCommand.Create('MyCommand', 33, ['par1','par2'], LS);
Resp := TAPClient.SendCommandWithResponse(TMClient.RemoteProfiles[0], ACommand);

На сервере в событии TAPServerAfterReceiveData эта команда перехватывается. Но я почему-то не могу вынуть переданный объект, а именно TStringList. Делаю так:
tc := TTetheringCommand.Create(TBytes(ADataBuffer));
 try
 memConnectedInfo.Lines.Add(tc.ToString);// TStringList(tc.Data)[0]
 if tc.Command = 'MyCommand'
  then
   begin
    memConnectedInfo.Lines.Add('Сообщ. ' + TStringList(tc.Data)[0]); 
    Resp := TTetheringCommand.Create('RetMyCommand', 3, [], tc.Data);
    Result := TByteDynArray(Resp.ToBytes); //это ни на что не влияет
   end
  else Result := ADataBuffer;
 except
  Result := ADataBuffer;
 end;

Срабатывает исключение при обращении TStringList(tc.Data)[0]. Что я делаю не так? Или в ADataBuffer объект отсутствует? На клиенте команда 'RetMyCommand' тоже получается, опять не могу получить данные переданного объекта. Правда делается это в событии TAPServerBeforeSendData:

 tc := TTetheringCommand.Create(TBytes(ADataBuffer));
 try
 memConnectedInfo.Lines.Add(tc.Command);
 if tc.Command = 'RES_BADCOM'
  then
   begin
    LS := TStringList.Create;
    LS.Add('Привет - это я с сервера!');
    Resp := TTetheringCommand.Create('RetMyCommand', 2, [], TObject(LS));
    Result := TByteDynArray(Resp.ToBytes);
    memConnectedInfo.Lines.Add(TTetheringCommand.Create(TBytes(Result)).ToString);
   end
  else Result := ADataBuffer;
 except

 end;

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

Проверка в TAPServerAfterReceiveData
 tc := TTetheringCommand.Create(TBytes(ADataBuffer));
 if tc.Data = nil возвращает ИСТИНУ. Объект действительно где-то пропал.

 

Изменено пользователем Wovan2
Дополнение

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
14 часов назад, Daniel Dorneles Peres сказал:

Ola.

Estava fazendo uma implementação usando Tethering e encontrei sua questão, mas tive de utilizar o google para traduzir, acho que terá de fazer o mesmo.

Também não gosto de usar socket (Indy) devido ao problema de não conseguir capturar a perda de conexão em algumas situações, o que acaba causando muitos problemas, então resolvi testar o Tether e até o momento estou gostando bastante. Estou utilizando recursos compartilhados, e tem se mostrado bem eficiente.

Peguei o seu caso pois estava tentando criar um log do que estava recebendo, e me deparei com o mesmo problema de parar o funcionamento dos recursos quando adiciono o evento AfterReceiveData. Fiz alguns testes e por tentativa e erro consegui fazer o código funcionar, embora não tenha entendido exatamente o porque do Result funcionar da forma como fiz, era uma tentativa para analisar os dados mas que acabou por funcionar.

Esse evento (AfterReceiveData) na verdade não reflete os dados que são modificados em tempo real, mas os recursos e ações que estão disponíveis em ambos os lados, pelo menos no que se refere aos recursos e ações "persistentes", acredito que para os recursos "transitórios" esse evento possa funcionar, mas não testei ainda.

Se colocar o código abaixo em um memo, conseguira entender um pouco do que quero dizer.

blah blah blah  

Espero ter ajudado de alguma forma.

 

 

Ola!

Guy, you are on Russian forum and almost nobody here understand your language. So please, i repeat: please, write on russian or on english.
And yeach, have a nice day! 😃

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 03.11.2017 в 14:13, Wovan2 сказал:

Не могу найти ни одного примера использования. Даже в хелпе Delphi:huh:

Посмотрите в идущих в комплекте примерах:

Тут \Object Pascal\Multi-Device Samples\Device Sensors and Services\App Tethering\ :

  • MediaPlayer
  • PhotoWall

И тут \Object Pascal\RTL\Tethering\ :

  • BDShoppingList
  • DesktopBeaconCast
  • DesktopCast
  • MediaPlayer
  • PhotoWall

А в общих чертах как то так:

Вы получаете на "сервере" данные ни где нибудь, а в событии

procedure TForm1.TetheringAppProfile1ResourceReceived(const Sender: TObject;  const AResource: TRemoteResource);

Переменная AResource - все что вам нужно. Там и полученные данные AResource.Value определенного типа AResource.Value.DataType. И профиль отправителя AResource.Profile позволяющий точно его идентифицировать. 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Похожий контент

    • От Pax Beach
      Коллеги, помогите пожалуйста с поиском решения.

      Есть зал 100x100 метров, 400-600 человек на борту. На их мобильные устройства (смартфоны, планшеты) нужно принимать раз в секунду различный текст ~120 символов в кодировке UTF8. Можно широковещательно, или P2P.
      Сейчас мы выбираем технологию передачи данных в ограниченном помещении большому количеству людей.
      От выбора инфраструктуры, понятно, зависит логика мобильных приложений для этой цели. 
       
      1. Как лучше выстроить инфраструктуру?
      2. Чем лучше рассылать Bluetooth или Wi-Fi (понятно, что GPRS канал в таком скоплении — не вариант, базовая станция не справятся, да и сигнала может не быть)?
      3. Сколько точек доступа и каких лучше разместить?
      4. На какие нюансы обратить внимание?
       
      Сначала я обратился к технологии маячков. Но по многим параметрам маячки здесь не подходят.
      Однако, не исключаю возможность широкого вещания по Bluetooth каналу.
      Так же возможно использовать технологию тетеринг (tethering), раздавать сигнал через смартфоны раскинутые по залу.
      Можно тоже самое организовать, раскидав точки доступа Wi-Fi.
      Преимущества той или иной инфраструктуры для меня не очевидны.
       
      Может кто-то сталкивался с подобными задачами?
      Заранее благодарю за участие в обсуждении.
       
       
       
    • От Рагим
      Доброго времени суток.
       
      Столкнулся со следующей проблемой: есть два приложения на Андроид. Подключаются друг к другу через Tethering. Когда оба телефона подключены к одной сети, все работает без проблем. Если на одном из телефонов создать точку доступа и подключить второй к этой сети, то они не подключаются друг к другу через Tethering. В чем может быть проблема?
    • От TAZAQ
      Доброго времени суток, посмотрел видео от embarcadero, там показывалась передача видео на другой девайс. Собственно, интересует передача самих данных - строк/файлов. Есть ли у кого примеры/проекты по этой теме?
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу