Перейти к содержанию
Fire Monkey от А до Я

Wovan2

Пользователи
  • Постов

    45
  • Зарегистрирован

  • Посещение

Весь контент Wovan2

  1. Без Utf8ToAnsi сервер (это серверный код) пишет "Привет". Свойство s.Encoding только для чтения. Пока помогает только прямое перекодирование, как в предыдущем моем ответе.
  2. Пока докопался до следующего. В Delphi строка закодирована в ANSI. (Или в Windows???) Замена на сервере s.WriteString('И тебе привет');//AnsiToUtf8 And You, Hi на a := TEncoding.ANSI.GetBytes('И тебе привет'); s.Write(TEncoding.Convert(TEncoding.ANSI, TEncoding.UTF8, a), Length(a) * 2); где a : TBytes; решает проблему. Только как-то вроде не красиво. Может как можно поизящнее переписать? Другими функциями, которых дофига и больше?
  3. Здравствуйте. Немного предыстории. Нужно соорудить клиент-сервер. Клиент на Android, сервер на Windows. Собственно перебираю варианты. 1. Сделал с помощью DataSnap. Работает. Но очень громоздко и не понятно. 2. Tethering. Так и не смог реализовать обмен данными между сервером и клиентом типа запрос-ответ. 3. IdTCPClient, IdTCPSever. Раньше (D7) опыт работы отрицательный, но в FMX, видимо, альтернативы нет. Так что сейчас предварительно реализую простой диалог запрос-ответ. Причем все вроде работает. И кода немного и быстро. НО. Уперся в кодировку. На клиенте (Android) не получается прочитать кириллицу. Сначала пробовал общаться Read, Write и передавать просто строки. Пробовал всякие индийские компоненты для кодировки. Но без понимания ничего и не получилось. В интернете где-то наткнулся на предложение передавать потоками. Реализовал. Стало лучше, но проблема с кодировкой не пропала. Скажем так, эта проблема уменьшилась вдвое. На стороне сервера все ОК. На стороне клиента либо знаки "????", либо ромбики с вопросами, либо ошибка "No mapping for the unicode character exists in the target multi-byte code page". Это я бессистемно перебирал варианты кодировок. К сожалению до сих пор так и не понимаю эти перекодировки. Вернее не так. Не понимаю откуда и куда идут какие кодировки. В общем помогите пожалуйста советом или кодом. Ниже код с которым экспериментирую. (код не большой) Сервер procedure TForm1.IdTCPServerExecute(AContext: TIdContext); var s : TStringStream; begin s := TStringStream.Create; mem.Lines.Add(AContext.Connection.Socket.Binding.PeerIP); AContext.Connection.IOHandler.ReadStream(s); s.Position := 0; mem.Lines.Add(Utf8ToAnsi(s.ReadString(s.Size))); s.Free; s := TStringStream.Create; s.WriteString('И тебе привет');// And You, Hi с этим все нормально, проблема только с русскими буквами s.Position := 0; AContext.Connection.IOHandler.Write(s,s.Size,true); //здесь s.Size = 13. в 26 никак не получается превратить, может быть тут что-то? s.Free; end; Клиент procedure TfrmMainClient.btn1Click(Sender: TObject); var s:TStringStream; begin s := TStringStream.Create; try IdTCPClient.Connect; if IdTCPClient.Connected then mem.Lines.Add('Есть контакт с сервером ' + IdTCPClient.Socket.Binding.PeerIP); s.WriteString('Привет'); s.Position := 0; IdTCPClient.IOHandler.Write(s, s.Size, true);//здесь заметил, что s.Size = 12, похоже на unicode s.Clear; IdTCPClient.IOHandler.ReadStream(s); s.Position := 0; Mem.Lines.Add(s.ReadString(s.Size)); //ошибка здесь finally IdTCPClient.Disconnect; if Assigned(s) then s.Free; end; end; Этот код приводит на клиента к ошибке "No mapping for the unicode character exists in the target multi-byte code page". На сервере сообщение "Привет" видно нормально. Помогите, кто чем может. ЗЫ. Тему "Как Получить текст по TCP (Indy) в нужной кодировке?" смотрел. Но либо она не актуальна (инди уже изменился), либо я не смог правильно понять. По крайней мере пробовал использовать это в самом начале, когда пытался передавать строки напрямую. В указанном коде IIdTextEncoding не представляю куда и как вставить. зы2: Извините. Пишу на Delphi 10.2. Indy 10.6.2(в комплекте с Delphi). Windows 10. Android 4 и 5
  4. Wovan2

    SendCommandWithResponse

    И снова здравствуйте. Хотя и разговариваю сам с собой, но все же, может кто еще и откликнется. В общем продолжаю мучить 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 возвращает ИСТИНУ. Объект действительно где-то пропал.
  5. Wovan2

    SendCommandWithResponse

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

    SendCommandWithResponse

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

    SendCommandWithResponse

    Порядок событий на сервере TAPServerBeforeSendData wrWc0I8ol7 TAPServerAfterReceiveData [пустая строка] TAPServerBeforeSendData {7FCD2085-28F1-4B42-9446-A73A0BC2873F} TAPServerAfterReceiveData {38BAA5D2-B0C3-E711-8018-AF8831B0713E} TAPServerBeforeSendData Error TAPServerAfterReceiveData [пустая строка] TAPServerAfterReceiveData [пустая строка] После имени события выводится свойство TTetheringCommand.Command (как в коде выше) Визуально похоже на обмен пакетами при сетевом общении Сперва хеш пароля, потом обмен адресами, потом передача произвольных данных (в моем случае пустые объекты) Ни у кого никаких мыслей не возникает? Мне бы понять в каком месте на сервере можно заполнить структуру ответа. Попытка покопаться в исходных кодах ни к чему не привела. Есть интересная процедура DoOnIncomingData, но по какому событию она запускается я не понял. Соответственно никакого события OnIncomingData у объекта TTetheringAppProfile нет.
  8. Wovan2

    SendCommandWithResponse

    На клиенте выполняю следующий код: 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'. Ни одного примера в во всем инете не нашел. Эту статью тоже штудировал. Мало чем отличается по содержанию от всех остальных. Разве немного подробнее. Но TTetheringCommand нет и там.
  9. Wovan2

    SendCommandWithResponse

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

    SendCommandWithResponse

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

    SendCommandWithResponse

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

    SendCommandWithResponse

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

    SendCommandWithResponse

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

    SendCommandWithResponse

    Здравствуйте. Пытаюсь через Tethering получить данные с удаленного приложения. Но все реализовано через события, и при наличии нескольких клиентов у меня возникла путаница, какому клиенту, что вернуть. Покопался в компоненте профиля и нашел функцию SendCommandWithResponse. По описанию, вроде, то, что мне нужно. Посылаю что-то конкретному профилю и получаю конкретно мне предназначенный ответ. Беда в том, я не нашел как с этим работать. Вообще про команды ничего не нашел, даже не английском. Похожих событий на принимающей стороне не нашел. Ведь вызвать функцию на клиенте - пол дела. Надо чтобы сервер обработал запрос и вернул результат. Или что-то не понимаю. Может кто может хотя бы намекнуть в какую сторону искать.
  15. Активность на этом форуме не очень. Видимо из-за того, что все только учатся сами. В общем, поковырялся и вытащил считанный код с помощью следующего оператора bc := JStringToString(csIntent.getStringExtra(StringToJString('barcode_string'))) Всем спасибо.
  16. Может отсюда http://developer.alexanderklimov.ru/android/theory/airplanemode.php можно что-то выжать? Написано на С#, но, в принципе, код понятен.
  17. Здравствуйте. Пишу на Delphi 7. И все было нормально пока не у нас не появился терминал сбора данных на Androide. На Delphi 10 написал простенькое приложение. Но тут встала проблема с занесением данных в поле ввода со сканера штрихкода. В инете нашел, что это дело просто решается интентами. Вообще в windows я подобное делал: вешал процесс, следящий за com-портом, и при появлении данных на нем пересылал их куда надо. В Android должно быть не сложнее. Но я запутался во всей этой куче параметров и функций, передаваемых и получаемых "намерениями". В общем вот что мы имеем на данный момент. В настройках сканера прописано: Intent output - android.intent.ACTION_DECODE_DATA Intent string extra - barcode_string На просторах нашел запуск BroadcastReceiver. На событие получения сообщения повесил ed.Text := JStringToString(csIntent.getExtras.getString(TJIntent.JavaClass.EXTRA_INTENT)); где csIntent параметр из BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent); Но ничего не выходит. Я подозреваю, что данные из сканера где-то в структуре csIntent. Но, к сожалению, в отладке дальше адреса этой переменной пробраться не получилось. Причем строка ed.Text := JStringToString(csIntent.getAction); возвращает в Text название интента: "android.intent.ACTION_DECODE_DATA". Помогите разобраться со структурой JIntent. Спасибо.
×
×
  • Создать...