| 
| 
 | Вопрос # 2 898/ вопрос открыт / | 
 |  Здравствуйте, уважаемые эксперты!
 Вопрос по компонентам Indy10 для Delphi: TIdTCPClient и TIdTCPServer.
 Написал по книге простого клиента и сервер с помощью TIdTCPClient и TIdTCPServer. Все хорошо, за исключением того, что русский текст не правильно отображается на сервере. Я так понял, что возможно необходимо манипулировать с кодировкой. Подскажите, а лучше напишите пример, как правильно считать русский текст из TEdit на клиенте, в каком виде отправить его в сеть, как принять (преобразовать) на сервере перед отображенеим в TMemo.
 Использую Delphi2009
 Нашел еще пример с функциями:
 function ToOEM(S: string): string;
 begin
 Result := '';
 if S = '' then Exit;
 SetLength(Result, Length(S));
 CharToOem(PWideChar(S), PANSIChar(Result));
 end;
 
 function FromOEM(S: string): string;
 begin
 Result := '';
 if S = '' then Exit;
 SetLength(Result, Length(S));
 OEMToChar(PANSIChar(S), PWideChar(Result));
 end;
 
 но их применение также не помогло.
 Приложение:Переключить в обычный режим unit Main; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,  IdEcho, ComCtrls, IdCoder, IdCoder3to4, IdCoderMIME; type  TMainForm = class(TForm)    StatusBar1: TStatusBar;    Memo1: TMemo;    Edit1: TEdit;    IdEcho1: TIdEcho;    Label1: TLabel;    Edit2: TEdit;    Label2: TLabel;    Button1: TButton;    IdDecoderMIME1: TIdDecoderMIME;    IdEncoderMIME1: TIdEncoderMIME;    procedure Button1Click(Sender: TObject);  private    { Private declarations }  public    { Public declarations }  end; var  MainForm: TMainForm;   function ToOEM(S: string): string;  function FromOEM(S: string): string;  function FixString(const AData: String): String; implementation {$R *.dfm} function ToOEM(S: string): string;begin  Result := '';  if S = '' then Exit;  SetLength(Result, Length(S));  CharToOem(PWideChar(S), PANSIChar(Result));end; function FromOEM(S: string): string;begin  Result := '';  if S = '' then Exit;  SetLength(Result, Length(S));  OEMToChar(PANSIChar(S), PWideChar(Result));end; function FixString(const AData: String): String;type  TW1252 = type AnsiString(1252);var  W1252: TW1252;  S: RawByteString;begin    SetLength(S, Length(W1252));  Move(Pointer(W1252)^, Pointer(S)^, Length(W1252));   SetCodePage(S, 1251, False);   Result := S;end;  procedure TMainForm.Button1Click(Sender: TObject);begin  try    IdEcho1.Host := Edit1.Text;    IdEcho1.Connect;    try      Memo1.Text := IdEcho1.Echo(Edit2.Text);    finally      IdEcho1.Disconnect;    end;  except   end;end; end.
|  |   Вопрос задал: Roman Novikov (статус: Посетитель)Вопрос отправлен: 11 июня 2009, 01:36
 Состояние вопроса: открыт, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 7; последнее сообщение — 12 июня 2009, 19:06; участников в обсуждении: 2. 
|   | Вадим К (статус: Академик), 11 июня 2009, 02:17 [#1]:Если клиент и сервер написаны на 2009 делфи и в коде Вы не делали никаких преобразований строки, то текст ОБЯЗАН отображаться правильно. Может быть только один случай - когда на сервере просто физически нет нужного шрифта.
 Код, который Вы показали, похож на код сервера, но это код плохого сервера. (сервер сам принимает данные от клиентов, а не ждет, пока нажмут кнопку). К тому же, в приведённом коде нет ни слова о TIdTCPClient и TIdTCPServer. Это точно тот пример, о котором Вы говорите?
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Roman Novikov (статус: Посетитель), 11 июня 2009, 12:53 [#2]:Код простого сервера. Он принимает сообщения от клиентов и выводит в TMemo. 
 unit MyServer;
 
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
 StdCtrls, IdContext;
 
 type
 TForm1 = class(TForm)
 IdTCPServer1: TIdTCPServer;
 Memo1: TMemo;
 Button1: TButton;
 Label1: TLabel;
 procedure IdTCPServer1Execute(AContext: TIdContext);
 procedure FormClose(Sender: TObject; var Action: TCloseAction);
 procedure Button1Click(Sender: TObject);
 private
 { Private declarations }
 public
 { Public declarations }
 end;
 
 var
 Form1: TForm1;
 
 implementation
 
 {$R *.dfm}
 
 procedure TForm1.Button1Click(Sender: TObject);
 begin
 IdTCPServer1.Active := not IdTCPServer1.Active;
 if IdTCPServer1.Active
 then Label1.Caption := 'Connected'
 else Label1.Caption := 'DisConnected';
 end;
 
 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
 begin
 IdTCPServer1.Active := False;
 Action := caFree;
 end;
 
 procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
 var l: string;
 begin
 l := AContext.Connection.IOHandler.ReadLn();
 Memo1.Lines.Add(l);
 end;
 
 end.
 
 
 
 
 Код простого клиента. Он подключается к клиенту при запуске и отправляет сообщение после нажетия кнопки.
 
 unit MyClient;
 
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
 IdMessage;
 
 type
 TForm1 = class(TForm)
 Edit1: TEdit;
 IdTCPClient1: TIdTCPClient;
 Button1: TButton;
 procedure Button1Click(Sender: TObject);
 procedure FormCreate(Sender: TObject);
 procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
 { Private declarations }
 public
 { Public declarations }
 end;
 
 var
 Form1: TForm1;
 
 implementation
 
 {$R *.dfm}
 
 procedure TForm1.Button1Click(Sender: TObject);
 begin
 //IdTCPClient1.Connect;
 IdTCPClient1.IOHandler.WriteLn(Edit1.Text);
 //IdTCPClient1.Disconnect;
 end;
 
 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
 begin
 IdTCPClient1.Disconnect;
 end;
 
 procedure TForm1.FormCreate(Sender: TObject);
 begin
 IdTCPClient1.Connect;
 end;
 
 end.
 
 
 
 Запускаю клиента и затем несколько клиентов на одном своем компьютере. Отправляю с клиентов сообшение "Hello world!", все приходит без проблем. Если же я пишу на клиенте русский текст "Здравствуйте, товарищи!", то на сервер в TMemo  приходит "????????????, ????????!". Говорят что в в исходниках Indy есть ошибка при работе с юникодом. У меня Delphi2009, Indy 10.2.5. Как сделать чтобы приходил русский текст?
 |  
|   | Вадим К (статус: Академик), 11 июня 2009, 13:04 [#3]:Странно, должно работать. надо будет дома посмотреть, что они там умудрились "поломать в коде". Это же надо специально сломать. А пока - можно просто использовать передачу строки через буфер, а не напрямую.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Roman Novikov (статус: Посетитель), 11 июня 2009, 13:21 [#4]:Я уже несколько дней копаюсь в инете, такая проблема не только у меня. Еще может подскажете сниффер, чтобы проверить по трафику что в сеть уходит/приходит? |  
|   | Вадим К (статус: Академик), 11 июня 2009, 13:35 [#5]:я пользуюсь Wireshark (он же Ethereal в молодости) (http://www.wireshark.org) Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Roman Novikov (статус: Посетитель), 12 июня 2009, 16:00 [#6]:Как у вас дела? Что-нибудь прояснилось? |  
|   | Roman Novikov (статус: Посетитель), 12 июня 2009, 19:06 [#7]:Я нашёл ответ на свой вопрос. В методах Readln(TIdEncoding) и Writeln(string, TIdEncoding) необходимо в качестве параметра TIdEncoding прописывать констатну enUTF8 (TIdEncoding = (enDefault, enANSI, enUTF8)  . При этом в разделе Uses подключить IdGlobal.
 Итак, рабочий клиент и сервер выглядят следующим образом:
 
 
 //*******************//
 //*Клиентский модуль*//
 //*******************//
 
 unit MyClient;
 
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
 IdMessage, ComCtrls, ToolWin, ActnMan, ActnCtrls, ActnMenus, ExtCtrls,
 PlatformDefaultStyleActnCtrls, ActnList, IdException, IdGlobal;
 
 type
 TForm1 = class(TForm)
 IdTCPClient1: TIdTCPClient;
 Button1: TButton;
 StatusBar1: TStatusBar;
 ActionMainMenuBar1: TActionMainMenuBar;
 RichEdit1: TRichEdit;
 ActionManager1: TActionManager;
 Splitter1: TSplitter;
 RichEdit2: TRichEdit;
 ControlBar1: TControlBar;
 ToolBar1: TToolBar;
 ToolButton1: TToolButton;
 ToolButton2: TToolButton;
 ToolButton3: TToolButton;
 ToolButton4: TToolButton;
 ToolButton5: TToolButton;
 Panel1: TPanel;
 Action1: TAction;
 Action2: TAction;
 procedure Button1Click(Sender: TObject);
 procedure FormClose(Sender: TObject; var Action: TCloseAction);
 procedure Action2Execute(Sender: TObject);
 procedure Action1Execute(Sender: TObject);
 private
 { Private declarations }
 public
 { Public declarations }
 end;
 
 var
 Form1: TForm1;
 function ToOEM(S: string): string;
 function FromOEM(S: string): string;
 
 implementation
 
 {$R *.dfm}
 
 //Подключение к серверу
 procedure TForm1.Action1Execute(Sender: TObject);
 begin
 with IdTCPClient1 do
 if (Connected)
 then
 try
 Disconnect;
 StatusBar1.Panels[0].Text := 'Статус: Отключен';
 except
 on E: Exception do
 begin
 ShowMessage('Ошибка VCL: ' + E.Message);
 end;
 end
 else
 try
 Connect;
 StatusBar1.Panels[0].Text := 'Статус: Подключен';
 except
 //Обработка ошибок подключения
 on E: EIdException do
 begin
 ShowMessage('Ошибка подключения: ' + E.Message);
 end;
 on E: Exception do
 begin
 ShowMessage('Ошибка VCL: ' + E.Message);
 end;
 end;
 end;
 
 //Отправка сообщения
 procedure TForm1.Button1Click(Sender: TObject);
 begin
 with IdTCPClient1 do
 if (Connected)
 then
 try
 IOHandler.WriteLn(RichEdit2.Text, enUTF8);
 RichEdit1.Lines.Append(RichEdit2.Text);
 RichEdit2.Lines.Clear;
 except
 //Обработка ошибок передачи сообщения
 on E: EIdException do
 begin
 ShowMessage('Ошибка передачи сообщения' + E.Message);
 end;
 on E: Exception do
 begin
 ShowMessage('Ошибка VCL' + E.Message);
 end;
 end
 else
 ShowMessage('Необходимо подключиться к серверу');
 end;
 
 //Закрытие формы через меню
 procedure TForm1.Action2Execute(Sender: TObject);
 begin
 Self.Close;
 end;
 
 //Закрытие формы
 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
 begin
 IdTCPClient1.Disconnect;
 Action := caFree;
 end;
 
 end.
 
 
 
 
 //******************//
 //*Серверный модуль*//
 //******************//
 
 unit MyServer;
 
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
 StdCtrls, IdContext, ComCtrls, ActnCtrls, ToolWin, ActnMan, ActnMenus,
 PlatformDefaultStyleActnCtrls, ActnList, IdException, IdGlobal;
 
 type
 TForm1 = class(TForm)
 IdTCPServer1: TIdTCPServer;
 StatusBar1: TStatusBar;
 ActionMainMenuBar1: TActionMainMenuBar;
 CoolBar1: TCoolBar;
 ActionManager1: TActionManager;
 ToolBar1: TToolBar;
 ToolButton1: TToolButton;
 ToolButton2: TToolButton;
 ToolButton3: TToolButton;
 ToolButton4: TToolButton;
 ToolButton5: TToolButton;
 Action1: TAction;
 Action2: TAction;
 RichEdit1: TRichEdit;
 procedure IdTCPServer1Execute(AContext: TIdContext);
 procedure FormClose(Sender: TObject; var Action: TCloseAction);
 procedure Action2Execute(Sender: TObject);
 procedure Action1Execute(Sender: TObject);
 private
 { Private declarations }
 public
 { Public declarations }
 end;
 
 var
 Form1: TForm1;
 
 implementation
 
 {$R *.dfm}
 
 //Активация сервера
 procedure TForm1.Action1Execute(Sender: TObject);
 begin
 try
 IdTCPServer1.Active := not IdTCPServer1.Active;
 if IdTCPServer1.Active
 then StatusBar1.Panels[0].Text := 'Статус: Активен'
 else StatusBar1.Panels[0].Text := 'Статус: Не активен';
 except
 on E: EIdException do
 begin
 ShowMessage('Ошибка активации: ' + E.Message);
 end;
 on E: Exception do
 begin
 ShowMessage('Ошибка VCL: ' + E.Message);
 end;
 end;
 end;
 
 //Закрытие формы через меню
 procedure TForm1.Action2Execute(Sender: TObject);
 begin
 Self.Close;
 end;
 
 //Закрытие формы
 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
 begin
 try
 IdTCPServer1.Active := False;
 StatusBar1.Panels[0].Text := 'Статус: Не активен';
 Action := caFree;
 except
 end;
 end;
 
 //Обработка входящего сообщения
 procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
 var l: string;
 begin
 try
 l := TrimRight(AContext.Connection.IOHandler.ReadLn(enUTF8));
 RichEdit1.Lines.Append(l);
 except
 //Обработка ошибок получения сообщения
 on E: EIdException do
 begin
 ShowMessage('Ошибка получения сообщения: ' + E.Message);
 end;
 on E: Exception do
 begin
 ShowMessage('Ошибка VCL: ' + E.Message);
 end;
 end;
 end;
 
 end.
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |