Indy 10 TCPServer не связывается с подключенными клиентами в Linux - PullRequest
1 голос
/ 14 октября 2011

У меня есть проблема, которая ведет меня к стене .Я пытаюсь перенести серверную часть клиент-серверного приложения Indy 10 в Windows на Linux, чтобы сэкономить средства.Приложение изначально разрабатывалось с использованием Delphi 2010. С тех пор я перенес его на Lazarus / FreePascal, и оно отлично работает на Windows.Учитывая, что Lazarus / FreePascal является мультиплатформенным и бесплатным, он является идеальным кандидатом для этой работы.

Я приложил все усилия, чтобы серверное приложение работало в Linux без успеха.Сервер просто не связывается с подключенными клиентами.Ничего общего!

Затем я решил вернуться к исходной точке.Я попытался получить очень простой пример для работы на Linux.Соответствующие части исходного кода показаны ниже:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
  s: string;
  i: Integer;
begin
  with AContext.Connection.IOHandler do
  try
    WriteLn('Type an integer and Enter');
    s := ReadLn;
    try
      i := StrToInt(s);
      WriteLn(s + ' squared is ' + IntToStr(i*i));
    except
      WriteLn(s + ' is not an integer');
    end;
  finally
    Free;
  end;
end;

procedure TForm1.FormActivate(Sender: TObject);
var
  Binding: TIdSocketHandle;
begin
  {$IFDEF UNIX}
  Binding := IdTCPServer1.Bindings.Add;
  //Binding.IPVersion := Id_IPv4;   <----- Gives compilation error Error: Identifier not found "Id_IPv4"
  {$ENDIF}
  Binding.IP := '127.0.0.1';
  Binding.Port := 6501;
  IdTCPServer1.Active := True;
end;

end.

Это файл проекта программы squares.lpr

program squares;

{$mode objfpc}{$H+}
// The following line is is necessary for Linux thread support            
{$IFDEF UNIX}{$DEFINE UseCThreads}{$ENDIF}     

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, uSquares
  { you can add units after this };

{$R *.res}

begin
  RequireDerivedFormResource := True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Когда я пытаюсь подключиться к серверу с терминала, используяtelnet, я получаю следующий ответ

telnet 127.0.0.1 6501
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
7
Connection closed by foreign host.

Как видите, telnet подключается к серверу.Но первый ответ сервера после подключения клиента «Введите целое число и Enter» не отображается.Кроме того, когда я отправляю число на сервер, например, «7» для квадрата, telnet говорит «Соединение закрыто внешним хостом».Таким образом, клиент telnet также не получает ответы сервера вообще.Я использую версию Indy SVN, так что речь не идет о старой версии Indy.

Так что даже этот базовый пример не работает в Linux!Я не знаю, как решить эту проблему, поэтому мне очень нужна ваша помощь.Кроме того, если у вас есть какие-либо материалы, которые я могу прочитать о программировании сокетов в Linux с использованием Pascal, я буду очень признателен.

Я использую Lazarus 0.9.31 / FPC 2.4.4 и Indy 10.5.8в Linux Mint.

JDaniel

Ответы [ 2 ]

2 голосов
/ 16 октября 2011

Id_IPv4 определено в IdGlobal.pas, убедитесь, что в вашем предложении uses указан юнит. Обратите внимание, что вы вызываете Bindings.Add() только если определен UNIX, но вы пытаетесь получить доступ к Binding за пределами блока IFDEF. Вам не нужен блок IFDEF вообще. Indy по умолчанию IPv4.

Что касается проблемы связи, я не вижу ничего плохого в показанном вами коде, если FreePascal правильно вызывает TIdIOHandler.WriteLn(), а не какую-то консольную подпрограмму ввода-вывода WriteLn (). Можете ли вы показать код клиента?

На стороне сервера, единственное, о чем я сейчас могу думать, что это может пойти не так, это возможный сбой в классе TIdTextEncoding в Indy при отправке / получении строк, если вы установили свойство TIdIOHandler.DefStringEncoding или глобальную переменную GIdDefaultEncoding в кодировку не по умолчанию. В системах, отличных от Windows, TIdTextEncoding использует библиотеку iconv, и поддержка iconv в Indy, как известно, в настоящее время немного ошибочна. С другой стороны, стандартная кодировка Indy - ASCII, которая вообще не использует iconv, поэтому при этом не должно быть сбоев.

0 голосов
/ 17 октября 2011

@ Реми Лебо. Я нашел ответ. Я играл с кодировкой текста, пока не получил код, который работает ниже:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
  s: string;
  i: Integer;
begin
  with AContext.Connection.IOHandler do
  try
    {$IFDEF UNIX}
    DefStringEncoding := TIdTextEncoding.Default
    {$ENDIF}
    WriteLn('Type an integer and Enter');
    s := ReadLn;
    try
      i := StrToInt(s);
      WriteLn(s + ' squared is ' + IntToStr(i*i));
    except
      WriteLn(s + ' is not an integer');
    end;
  finally
    Free;
  end;
end;

procedure TForm1.FormActivate(Sender: TObject);
var
  Binding: TIdSocketHandle;
begin
  {$IFDEF UNIX}
  Binding := IdTCPServer1.Bindings.Add;
  Binding.Port := 6501;
  {$ENDIF}
  {IFDEF MSWINDOWS}
  IdTCPServer1.DefaultPort := 6501
  {$ENDIF} 
  IdTCPServer1.Active := True;
end;

Это ответ telnet:

telnet 127.0.0.1 6501
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Type an integer and Enter
7
7 squared is 49
Connection closed by foreign host.

Однако я все еще хотел бы знать, как я могу установить глобальную переменную GIdDefaultEncoding , чтобы я мог покончить с DefStringEncoding: = TIDTextEncoding.Default . Спасибо за вашу помощь.

...