Гость
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Кодировка при отправке через TCP / 23 сообщений из 23, страница 1 из 1
06.10.2021, 07:12
    #40102222
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
Есть приложение клиент TCP на android (не FMX), оно подключается к серверу на delphi

Старт сервера

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
var
  FIndySrv: TIdTCPServer;
begin
  FIndySrv:=TIdTCPServer.Create(nil);
  FIndySrv.DefaultPort:=50000;
  FIndySrv.OnExecute := DoOnIndyExecute;
  FIndySrv.OnConnect := DoConnect;
  FIndySrv.Active:=true;
end;



при отправке запроса с клиента выполняется
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
procedure DoOnIndyExecute(AContext: TIdContext);
var
 s : TStringStream;
 rev: string;
begin
  mmo1.Lines.Add(AContext.Connection.Socket.Binding.PeerIP);

  //Так получается конвертировать кириллицу
  rev := AContext.Connection.Socket.ReadLn(IndyTextEncoding(IdTextEncodingType.encUTF8));

  //в мемо пишется кириллица, всё хорошо
  mmo1.Lines.Add(rev);

  //Взад никак не получается отправить, что бы клиент на андроиде понял кириллицу

  AContext.Connection.Socket.WriteLn(rev,  IndyTextEncoding_UTF8); //ни так

  //Ни даже ч-з поток
  s := TStringStream.Create('', TEncoding.UTF8);
  s.WriteString('И тебе привет');
  s.Position := 0;
  AContext.Connection.IOHandler.Write(s,s.Size,true); 
  s.Free;
end;



пробовал менять кодировки, но в любом случае на андроиде кракозяблы, если делать клиента на delphi, то ч-з потоки всё норм

А так понимаю, что если принимаю в UTF8, то и возвращать надо в нем же, но не получается... Или я что-то не так делаю?
...
Рейтинг: 0 / 0
06.10.2021, 08:06
    #40102224
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,

Может в Delphi 10.x есть что-то более современно для организации сокетов?
...
Рейтинг: 0 / 0
06.10.2021, 09:58
    #40102251
Cobalt747
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,

в каком виде кракозябры-то хоть?
...
Рейтинг: 0 / 0
06.10.2021, 10:01
    #40102255
Cobalt747
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox
А так понимаю, что если принимаю в UTF8, то и возвращать надо в нем же, но не получается...

это надо у автора клиента уточнить, как минимум.
Может он в принципе кириллицу не способен отображать
...
Рейтинг: 0 / 0
06.10.2021, 10:12
    #40102266
DHDD
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,

Код: pascal
1.
2.
3.
4.
5.
IdIOHandler.pas
    procedure Write(const ABuffer: TIdBytes; const ALength: Integer = -1; const AOffset: Integer = 0); overload; virtual;
    procedure Write(const AOut: string; AByteEncoding: IIdTextEncoding = nil
      {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
      ); overload; virtual;



конвертация в utf:
UTF8Encode()
...
Рейтинг: 0 / 0
06.10.2021, 12:20
    #40102310
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
В сокете нет строк и кодировки. В сокете есть только байты. Поэтому отправка должна выглядеть так
Код: pascal
1.
2.
3.
4.
5.
6.
var
  Buf: TBytes;
begin
  Buf := TEncoding.UTF8.GetBytes(Str);  // Или любая другая кодировка, которую ожидает клиент
  Socket.Write(Buf, Length(Buf));  // Как передается длина пакета, смотрите в протоколе
end;

И чтение
Код: pascal
1.
2.
3.
4.
5.
6.
var
  Buf: TBytes;
begin
  Buf := Socket.Read(packetLen); 
  Str := TEncoding.UTF8.GetString(Buf);
end;
...
Рейтинг: 0 / 0
06.10.2021, 13:35
    #40102329
s62
s62
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
del, неправильно написал
...
Рейтинг: 0 / 0
06.10.2021, 13:41
    #40102339
X-Cite
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,

На событии OnConnect у TIdTCPServer надо задать

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TTcpContainer.TCPServerConnect(AContext: TIdContext);
begin
  AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding(IdTextEncodingType.encUTF8);
//  или можно так
//  AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding(65001);
end;



В самих методах Read/Write тогда можно не указывать.

Мы только так смогли победить кириллицу в 1251 используя что-то вроде этого
Код: pascal
1.
AContext.Connection.IOHandler.WriteLn('Текст');



P.S. не знаю на что влияет но пишем мы не через Socket, а через IOHandler
...
Рейтинг: 0 / 0
06.10.2021, 16:19
    #40102381
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
X-Cite
antox,

На событии OnConnect у TIdTCPServer надо задать

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TTcpContainer.TCPServerConnect(AContext: TIdContext);
begin
  AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding(IdTextEncodingType.encUTF8);
//  или можно так
//  AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding(65001);
end;



В самих методах Read/Write тогда можно не указывать.

Мы только так смогли победить кириллицу в 1251 используя что-то вроде этого
Код: pascal
1.
AContext.Connection.IOHandler.WriteLn('Текст');



P.S. не знаю на что влияет но пишем мы не через Socket, а через IOHandler


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

Видимо, надо с клиентом разбираться
...
Рейтинг: 0 / 0
06.10.2021, 16:20
    #40102382
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
Cobalt747
antox,

в каком виде кракозябры-то хоть?


Оч страшные :) Скрин чуть выше
...
Рейтинг: 0 / 0
06.10.2021, 16:21
    #40102384
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
DHDD
antox,

Код: pascal
1.
2.
3.
4.
5.
IdIOHandler.pas
    procedure Write(const ABuffer: TIdBytes; const ALength: Integer = -1; const AOffset: Integer = 0); overload; virtual;
    procedure Write(const AOut: string; AByteEncoding: IIdTextEncoding = nil
      {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
      ); overload; virtual;



конвертация в utf:
UTF8Encode()


При

Код: pascal
1.
AContext.Connection.Socket.Write(UTF8Encode('Привет'))



тот же результат
...
Рейтинг: 0 / 0
06.10.2021, 18:08
    #40102433
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox
Оч страшные :) Скрин чуть выше
UTF-8, который прочитали как Win1252
...
Рейтинг: 0 / 0
06.10.2021, 18:12
    #40102436
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,



... судя по всему означает ( если воспользоваться этим алгоритмом )
...
Рейтинг: 0 / 0
06.10.2021, 18:16
    #40102439
s62
s62
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
Похоже, клиент на Андроиде не может угадать кодировку, может быть в строке нет BOM'а? Это можно проверить и, в случае чего, добавить. Пишут , что не только в файле, но и в потоке BOM вставляют. Может в этом дело.
...
Рейтинг: 0 / 0
06.10.2021, 19:41
    #40102454
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
s62
Похоже, клиент на Андроиде не может угадать кодировку,
А зачем ему угадывать, если кодировка должна быть определена на уровне протокола?
...
Рейтинг: 0 / 0
06.10.2021, 20:02
    #40102459
s62
s62
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
_Vasilisk_
А зачем ему угадывать, если кодировка должна быть определена на уровне протокола?
Я не знаю, какой там протокол.

_Vasilisk_
В сокете нет строк и кодировки. В сокете есть только байты. Поэтому отправка должна выглядеть так
Код: pascal
1.
2.
3.
4.
5.
6.
var
  Buf: TBytes;
begin
  Buf := TEncoding.UTF8.GetBytes(Str);  // Или любая другая кодировка, которую ожидает клиент
  Socket.Write(Buf, Length(Buf));  // Как передается длина пакета, смотрите в протоколе
end;


И чтение
Код: pascal
1.
2.
3.
4.
5.
6.
var
  Buf: TBytes;
begin
  Buf := Socket.Read(packetLen); 
  Str := TEncoding.UTF8.GetString(Buf);
end;

Медоды ReadXXX и WriteXXX класса TIdIOHandler для чтения и записи разных типов данных выполняют такие преобразования, поэтому не обязательно делать это самому.
...
Рейтинг: 0 / 0
06.10.2021, 20:37
    #40102470
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
s62
, поэтому не обязательно делать это самому.
Обязательно, если не хочешь угадывать, что же там внутри у себя делает Инди. Вот у ТС угадать не получилось
...
Рейтинг: 0 / 0
06.10.2021, 20:54
    #40102478
s62
s62
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
_Vasilisk_,
у Инди в общем-то задокументировано, что посылается. ТС может быть пока не знает, что по протоколу посылать нужно.
Код: pascal
1.
public procedure Write(const AOut: string; AByteEncoding: TIdTextEncoding = nil); virtual; overload;


EmbWrite is an overloaded procedure used to write the specified data type using the IOHandler.
AOut is a string with the values to write using the IOHandler.
AEncoding is a TIdTextEncoding instance used for values in the string. The default value (Nil) causes the TIdTextEncoding instance in the DefStringEncoding property to be used for the operation.
Write converts the value in AOut to a TIdBytes data type, and calls an overloaded variant of the Write method using the bytes values and the specified text encoder as arguments.
Код: pascal
1.
public procedure WriteLn(const AOut: string; AByteEncoding: TIdTextEncoding = nil); virtual; overload;


EmbWriteLn is a virtual procedure used to write the string value specified in AOut using the IOHandler.
AEncoding is a TIdTextEncoding instance used for values in the string. The default value (Nil) causes the TIdTextEncoding instance in the DefStringEncoding property to be used for the operation.
WriteLn appends the EOL character sequence to the value in AOut, and calls the Write method to append the value to the write buffering mechanism for the IOHandler.
...
Рейтинг: 0 / 0
06.10.2021, 21:21
    #40102482
s62
s62
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,
может конечно дело вовсе не в этом, но можете попробовать добавить BOM в строку. Как у вас было с потоком, но с добавлением:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
const
  Bom: array[0..2] of byte = ($EF, $BB, $BF);
...
  s := TStringStream.Create('', TEncoding.UTF8);
  try
    s.Write(Bom, 3);
    s.WriteString('И тебе привет');
    s.Position := 0;
    AContext.Connection.IOHandler.Write(s,s.Size,true);
  finally 
    s.Free;
  end;
end;
...
Рейтинг: 0 / 0
06.10.2021, 21:32
    #40102483
s62
s62
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
antox,
авторпробовал менять кодировки, но в любом случае на андроиде кракозяблы, если делать клиента на delphi, то ч-з потоки всё норм

А так понимаю, что если принимаю в UTF8, то и возвращать надо в нем же, но не получается..Может быть клиенту на Java нужно указать явно, что он принимает строку UTF8? Если есть такая возможность.
...
Рейтинг: 0 / 0
06.10.2021, 21:54
    #40102485
shalamyansky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
авторесли делать клиента на delphi, то ч-з потоки всё норм

Т.е., следует понимать, улетает все как должно? Что ж вы тут голову всем морочите, все ваш сервер правильно делает. А проблема у клиента с интерпретацией приходящего. У JVM есть опция default charset, обычно она установлена в utf8, но может и отличаться. Задается флагом командной строки при запуске JVM. Этот умолчальный чарсет как раз и отвечает за преобразование массива байт во внутреннюю строку Java в том случае, когда явный чарсет не задан. Андроид русский, английский, китайский?..

Вам нужно или переписать клиента, указав при приеме чарсет явно, или настроить среду Java на default charset = utf8, или расширить протокол, и передавать вместе с текстом идентификатор чарсета. Соответственно, принимать этот идентификатор и производить нужные телодвижения.
...
Рейтинг: 0 / 0
06.10.2021, 22:17
    #40102486
shalamyansky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
Судя по вышеприведенной картинке, похоже, что у вас Java.defaultCharset = CP1252, он же ISO-8859-1, Андроид для Европы или Америки. И не ищите в Java ни windows-1251, ни windows-1252, их там нет. Только их синонимы.
...
Рейтинг: 0 / 0
07.10.2021, 05:58
    #40102509
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кодировка при отправке через TCP
Да, сервер работает правильно, клиент на flutter глючил

при получении конвертировал так:

Код: c#
1.
message: String.fromCharCodes(event)



поменял на:

Код: c#
1.
message: utf8.decode(event)



после этого все заработало нормально
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Кодировка при отправке через TCP / 23 сообщений из 23, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]