Home > Software engineering >  Indy TIdCmdTCPServer reading garbage
Indy TIdCmdTCPServer reading garbage

Time:06-28

I'm implementing a very simple TIdCmdTCPServer for receiving data from a cell phone application we also wrote. The cell application starts with a simple hello command, but the OnBeforeCommandHandler comes with garbage.

AData equals 'somerandomchars hello'

The random chars are non ASCII ones.

I'm using Delphi 2007 with the bundled Indy 10.1.5 components. I've tried this:

  • Maybe my program was creating some corruption so I made a very simple one with just a Form and a TIdCmdTCPServer. Same result.
  • Are the Delphi 2007 Indy components buggy? I switched to Delphi 10.3. Same problem.
  • Is my computer somehow corrupting the communication? I ran the simple program in other Windows 10, both physical and virtual. Got the same problem.
  • Maybe the cell application was sending wrong data. Tried using Putty to send the commands directly. No luck.
  • Different port? Same

I've searched for this problem but found not a single page. In fact, they all state running a TIdCmdTCPServer smoothly.

The most strange point is that after five or six commands, the data reads fine. On each event, the random chars are distinct from the previous one. After stepping through Indy code, I discovered that when it is about to read the very first time, it already has the random chars in the input buffer. Different "commands" need a different amount of cycles to begin reading without garbage. In the case of "hello", eight or nine times (not always the same).

What is causing this? I'm just starting the server with:

IdCmdTCPServer1.Active := True;

Does it need a separate thread? Indy's help doesn't say anything about that. No properties have been changed from the default ones.

Here is the code of the simple application:

unit test;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
  IdCmdTCPServer, IdCommandHandlers, IdContext, IdServerIOHandler,
  IdServerIOHandlerSocket, IdServerIOHandlerStack;

type
  TForm1 = class(TForm)
    cmdsMain: TIdCmdTCPServer;
    ioshMain: TIdServerIOHandlerStack;
    procedure FormShow(Sender: TObject);
    procedure cmdsMainCommandHandlers0Command(ASender: TIdCommand);
    procedure cmdsMainBeforeCommandHandler(ASender: TIdCmdTCPServer;
      var AData: string; AContext: TIdContext);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.cmdsMainBeforeCommandHandler(ASender: TIdCmdTCPServer;
  var AData: string; AContext: TIdContext);
begin
// here comes the garbagge
end;

procedure TForm1.cmdsMainCommandHandlers0Command(ASender: TIdCommand);
begin
//
end;

procedure TForm1.FormShow(Sender: TObject);
begin
cmdsMain.Active := True
end;

end.
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object cmdsMain: TIdCmdTCPServer
    Bindings = <
      item
        IP = '0.0.0.0'
        Port = 55
      end>
    DefaultPort = 55
    IOHandler = ioshMain
    CommandHandlers = <
      item
        CmdDelimiter = ' '
        Command = 'hello'
        Disconnect = False
        Name = 'TIdCommandHandler0'
        NormalReply.Code = '200'
        ParamDelimiter = ' '
        ParseParams = True
        Tag = 0
        OnCommand = cmdsMainCommandHandlers0Command
      end>
    ExceptionReply.Code = '500'
    ExceptionReply.Text.Strings = (
      'Unknown Internal Error')
    Greeting.Code = '200'
    Greeting.Text.Strings = (
      'Welcome')
    HelpReply.Code = '100'
    HelpReply.Text.Strings = (
      'Help follows')
    MaxConnectionReply.Code = '300'
    MaxConnectionReply.Text.Strings = (
      'Too many connections. Try again later.')
    ReplyTexts = <>
    ReplyUnknownCommand.Code = '400'
    ReplyUnknownCommand.Text.Strings = (
      'Unknown Command')
    OnBeforeCommandHandler = cmdsMainBeforeCommandHandler
    Left = 312
    Top = 152
  end
  object ioshMain: TIdServerIOHandlerStack
    Left = 376
    Top = 168
  end
end

UPDATE: We modified the cell app to just send the commands to an echo server: tcpbin.com. The echo was received fine. We emulated the cell to the same server using Putty just to ensure that it was generating any garbage. In both, it ran fine.

CodePudding user response:

The fact that you can reproduce the issue across multiple Indy versions and multiple server machines tells me the problem is likely not with the server at all, but with the client. For instance, if you are using Putty in telnet mode instead of raw mode.

  • Related