powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Кодировка при отправке через TCP
23 сообщений из 23, страница 1 из 1
Кодировка при отправке через TCP
    #40102222
antox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть приложение клиент 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
Кодировка при отправке через TCP
    #40102224
antox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
antox,

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

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

это надо у автора клиента уточнить, как минимум.
Может он в принципе кириллицу не способен отображать
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102266
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()
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102310
Фотография _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;
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102329
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
del, неправильно написал
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102339
Фотография 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
Кодировка при отправке через TCP
    #40102381
antox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Кодировка при отправке через TCP
    #40102382
antox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cobalt747
antox,

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


Оч страшные :) Скрин чуть выше
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102384
antox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Кодировка при отправке через TCP
    #40102433
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
antox
Оч страшные :) Скрин чуть выше
UTF-8, который прочитали как Win1252
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102436
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
antox,



... судя по всему означает ( если воспользоваться этим алгоритмом )
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102439
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Похоже, клиент на Андроиде не может угадать кодировку, может быть в строке нет BOM'а? Это можно проверить и, в случае чего, добавить. Пишут , что не только в файле, но и в потоке BOM вставляют. Может в этом дело.
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102454
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
s62
Похоже, клиент на Андроиде не может угадать кодировку,
А зачем ему угадывать, если кодировка должна быть определена на уровне протокола?
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102459
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_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
Кодировка при отправке через TCP
    #40102470
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
s62
, поэтому не обязательно делать это самому.
Обязательно, если не хочешь угадывать, что же там внутри у себя делает Инди. Вот у ТС угадать не получилось
...
Рейтинг: 0 / 0
Кодировка при отправке через TCP
    #40102478
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_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
Кодировка при отправке через TCP
    #40102482
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Кодировка при отправке через TCP
    #40102483
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
antox,
авторпробовал менять кодировки, но в любом случае на андроиде кракозяблы, если делать клиента на delphi, то ч-з потоки всё норм

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

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

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

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

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



поменял на:

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



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


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