Recent

Author Topic: Trying, and failing, to create a TCP Client  (Read 1918 times)

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Trying, and failing, to create a TCP Client
« on: September 04, 2025, 06:16:33 pm »
After pulling my hair out for a few hours now, I'm here to ask for help (which I'll probably solve myself now I've posted).

I'm trying to use Synapse and write a simple application to connect to a device to control it...it is actually an Extron DMP 128 which one can conenct to over TCP. So, a simple TCP Client. Except, I keep getting "No route to host". And, I can't find any answers.

Before now, I've written a TCP Server application, which was simple compared to this. I know it is not my firewall as the logs show the connection being allowed. Plus, doing the same thing with PacketSender works absolutely fine. Only difference is, with my application, the source IP is '0.0.0.0', but with PacketSender, it is my correct IP address (not sure if that is important or not).

Entire unit is:
Code: Pascal  [Select][+][-]
  1. unit MainUnit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls,
  9.  StdCtrls, blcksock;
  10.  
  11. type
  12.  
  13.  { TMainForm }
  14.  
  15.  TMainForm = class(TForm)
  16.    tbInputGain_ch1: TTrackBar;
  17.    Output: TMemo;
  18.    Button1: TButton;
  19.    procedure Button1Click(Sender: TObject);
  20.    procedure FormShow(Sender: TObject);
  21.  private
  22.   DMPIPAddress: String;
  23.   DMPPort     : Integer;
  24.  public
  25.  
  26.  end;
  27.  
  28. var
  29.  MainForm: TMainForm;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TMainForm }
  36.  
  37. procedure TMainForm.FormShow(Sender: TObject);
  38. begin
  39.  DMPIPAddress:='192.168.0.210';
  40.  DMPPort     :=23;
  41. end;
  42.  
  43. procedure TMainForm.Button1Click(Sender: TObject);
  44. var
  45.  sock: TTCPBlockSocket;
  46.  buffer: String = '';
  47. begin
  48.  Output.Lines.Add('Connecting to '+DMPIPAddress+' on port '+IntToStr(DMPPort));
  49.  sock := TTCPBlockSocket.Create;
  50.  sock.Connect(DMPIPAddress,IntToStr(DMPPort));
  51.  // Was there an error?
  52.  if sock.LastError=0 then
  53.  begin
  54.   repeat
  55.    buffer:=sock.RecvPacket(2000);
  56.    if not buffer.IsEmpty then Output.Lines.Add(buffer);
  57.   until buffer.IsEmpty;
  58.   Output.Lines.Add('Sending query');
  59.   sock.SendString('wG40001AU'#13#10);
  60.   repeat
  61.    buffer:=sock.RecvPacket(2000);
  62.    if not buffer.IsEmpty then Output.Lines.Add(buffer);
  63.   until buffer.IsEmpty;
  64.  end else Output.Lines.Add('Could not connect : '+sock.LastErrorDesc);
  65.  sock.Free;
  66. end;
  67.  
  68. end.
  69.  

This is on Lazarus 4 on macOS 15.6.1

440bx

  • Hero Member
  • *****
  • Posts: 5820
Re: Trying, and failing, to create a TCP Client
« Reply #1 on: September 04, 2025, 06:29:54 pm »
After pulling my hair out for a few hours now,
Lucky you... I couldn't pull my hair out for more than a few minutes now.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #2 on: September 04, 2025, 07:20:39 pm »
Lucky you... I couldn't pull my hair out for more than a few minutes now.
Trick is to have short hair so you can't grab a hold of it.  :D

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #3 on: September 05, 2025, 01:34:32 pm »
I appear to have honed in on the problem...well, not the exact issue.

Taking the same code and running it on a Windows PC and it runs fine and connects to the DSP without an issue. So, the problem is with macOS. However, PacketSender manages on a Mac, so there must be something I need to do, in the code, to persuade macOS to allow it to work.

Zvoni

  • Hero Member
  • *****
  • Posts: 3140
Re: Trying, and failing, to create a TCP Client
« Reply #4 on: September 05, 2025, 02:00:56 pm »
Did you "Bind" the socket to your local IP?

After creating your socket call
GetLocalSinIP/GetLocalSInPort
It should show your local IP
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #5 on: September 05, 2025, 04:40:04 pm »
Just tried. Same result.  :'(
Code: Pascal  [Select][+][-]
  1.  DMPIPAddress:='192.168.0.210';
  2.  DMPPort     :=23;
  3.  sock        :=TTCPBlockSocket.Create;
  4.  sock.Bind(sock.GetLocalSinIP,IntToStr(sock.GetLocalSinPort));
  5.  sock.Connect(DMPIPAddress,IntToStr(DMPPort));

Warfley

  • Hero Member
  • *****
  • Posts: 2021
Re: Trying, and failing, to create a TCP Client
« Reply #6 on: September 05, 2025, 05:41:16 pm »
First, why do you use synapse if you only need a raw TCP Stream, FCL got you covered without any need for external/third party dependencies:
Code: Pascal  [Select][+][-]
  1. uses
  2.   ssockets;
  3. [...]
  4. var
  5.   sock: TInetSocket;
  6. begin
  7.   sock:=TInetSocket.Create('IP', 1337);
  8.   try
  9.     sock.Connect;
  10.     sock.Write('Hello World', Length('Hello World'));
  11.   finally
  12.     sock.Free;
  13.   end;
  14. end;

Second, the error you are getting is directly coming from the underlying sockets API of the OS and it means the system cannot find a way to reach that IP address. There are a few options for that:
1. Your IP address is invalid
2. Your IP address may be read incorrectly (e.g. network and host byteorder mismatch)
3. Your device is not within a network that can reach that IP address.

First verify that the IP address is reachable from your PC (e.g. ping it). If that is the case use the debugger to check how the IP is transformed internally and if the 32bit int representation is correct. If both is the case and it still doesn't work, maybe you need to sacrifice a goat or something to appease the demons living in the NIC

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #7 on: September 05, 2025, 06:25:50 pm »
Hiya Warfley,

Answer to your first question...well, there's two: I couldn't remember the native units, and I've always been told that Synapse is better. However, just tried what you've suggested and I get the same result: failure to connect (well, it fails when trying to create the socket, before it's even connected).

I can easily connect, and talk to, the device in question from the Mac using PacketSender without an issue, using the same IP address and Port number.

So, how does one use the debugger to check how the IP address is transformed?

Finally, where can I get a goat? OK, I live in the Scottish Highlands...they wander wild up here!
Do I need a special altar or something? :D

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Trying, and failing, to create a TCP Client
« Reply #8 on: September 05, 2025, 06:39:29 pm »
and I've always been told that Synapse is better.
Although that has been the case for a very long time, it is also not true anymore for a very long time.

About your issue: any security involved? Or is it just what you asked, a raw tcp connection?
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #9 on: September 05, 2025, 07:23:10 pm »
I've removed the password from the device, so there will be no security involved. Didn't want to complicate things.

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Trying, and failing, to create a TCP Client
« Reply #10 on: September 05, 2025, 07:38:23 pm »
In that case, is there a policy blocking a port? That can be a antivirus or a firewall. Usually these do not kick in on a local connection, though.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #11 on: September 05, 2025, 07:54:20 pm »
I've looked at those. It's being allowed, according to the log.
I've even turned off the Firewall (it was my first thought).

I've largely discounted policies because PacketSender works fine to the same device.
Code: [Select]
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
Communication allowed by rule Allowed 192.168.0.71:50282 192.168.0.210:23 TCP Out Allow outbound connections /Applications/PacketSender.app/Contents/MacOS/packetsender
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections /Applications/PacketSender.app/Contents/MacOS/packetsender
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
Communication allowed by rule Allowed 192.168.0.71:50270 192.168.0.210:23 TCP Out Allow outbound connections /Applications/PacketSender.app/Contents/MacOS/packetsender
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections /Applications/PacketSender.app/Contents/MacOS/packetsender
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
Communication allowed by rule Allowed 0.0.0.0 192.168.0.210:23 TCP Out Allow outbound connections
This was the output from ESET at yesterday's attempts.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12536
  • FPC developer.
Re: Trying, and failing, to create a TCP Client
« Reply #12 on: September 05, 2025, 09:53:27 pm »
Afaik policies on mac can be per app ?

Warfley

  • Hero Member
  • *****
  • Posts: 2021
Re: Trying, and failing, to create a TCP Client
« Reply #13 on: September 05, 2025, 10:44:30 pm »
Because I'm just at my phone for now and don't have access to any computer, so I can't give you the examples, but as you are on MacOS I'd do the following:
1. Check if netcat is working, its a command line utility shipped with MacOS that allows you to make easy network connections. Simply type "nc IP port" and it will open a TCP stream where you can send messages via the terminal.
If netcat doesn't work there's a system issue.
2. MacOS is a POSIX system, meaning the system API for networking is the Berkeley Sockets API provided by the C ABI. So to remove as many variables as possible I'd try to create a simple C program that connects to the server. Don't even bother with IP strings and write the connection data right into the address struct.
If that doesn't work it might be some app specific firewall
3. Now translate the C code 1-1 to Pascal. See the units sockets and baseunix which contain 1-1 equivalents of the C functions with the prefix fp (so instead of bind its fpbind)
If this doesn't work it can indicate to be either an FPC issue or potentially a code signing issue (that apples official development toolchain for C avoids)

geraldholdsworth

  • Sr. Member
  • ****
  • Posts: 265
Re: Trying, and failing, to create a TCP Client
« Reply #14 on: September 06, 2025, 11:58:10 am »
nc IP Port works.  :)

I have no idea how to write in C.

However, I found that this works:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses Sockets, SysUtils;
  4.  
  5. Var
  6.   SAddr    : TInetSockAddr;
  7.   Buffer   : string [255];
  8.   S        : Longint;
  9.   Sin,Sout : Text;
  10.   i        : integer;
  11.  
  12. begin
  13.  S:=fpSocket (AF_INET,SOCK_STREAM,0);
  14.  if s<>-1 then
  15.  begin
  16.   SAddr.sin_family:=AF_INET;
  17.   SAddr.sin_port:=htons(23);
  18.   SAddr.sin_addr.s_addr:=HostToNet(192<<24 or 168<<16 or 210);
  19.   if Connect (S,SAddr,Sin,Sout) then
  20.   begin
  21.    //Make first contact
  22.    Reset(Sin);
  23.    ReWrite(Sout);
  24.    repeat
  25.     Readln(SIn,Buffer);
  26.     if Buffer<>'' then WriteLn(Buffer);
  27.    until Buffer='';
  28.    Flush(Sout);
  29.    //Get the initial response
  30.    repeat
  31.     Read(SIn,Buffer);
  32.     if Buffer<>'' then WriteLn(Buffer);
  33.    until Buffer='';
  34.    //Send a query
  35.    Reset(Sin);
  36.    ReWrite(Sout);
  37.    Buffer:='wG40000AU'#$0D#$0A;
  38.    Write(Sout,Buffer);
  39.    Flush(Sout);
  40.    //Get the response
  41.    repeat
  42.     Read(SIn,Buffer);
  43.     if Buffer<>'' then WriteLn(Buffer);
  44.    until Buffer='';
  45.    Close(sout);
  46.   end;
  47.  end;
  48. end.
Found here.

Need some more research - need to work out how to put a time out on the reading part.

 

TinyPortal © 2005-2018