Dual bind IPv6 and IPv4

Hello,

I’m using the SDK in various projects and am faced with a situation where I want my servers to listen on the same port both in IPv4 and IPv6.
The first server is using TROIpSuperHTTPServer and it works by simply setting its BindV6 property to True
The second server is using TROSynapseSuperTCPServer and there is no such property. I thus tried this code:

ROControlServer.Server.BindList.Text :=
  '0.0.0.0:' + ROControlServer.Port.ToString + #13#10 +  // IPv4
  ':::' + ROControlServer.Port.ToString;  // IPv6

I successfully manages to bind to the IPv4 address but I keep getting an error with the IPv6, the code being “10022 - Invalid argument”
I tried using '[::]:' + ROControlServer.Port.ToString instead, but it does not change anything.

I have found the following discussion: Use TROIpSupperHTTPServer with IPV6
Where it suggests modifying the value of SockEnhancedApi but removing any code that sets its value inside InitSocketInterface leads to an error. This time it is “11004 - Valid name, no data record of requested type”

What works, though, is to only give the IPv6 binding to the server. So, does TROSynapseSuperTCPServer support dual binding like TROIpSuperHTTPServer does or should I create two instances? And if I create two instances, will it work flawlessly?

And then there are all the other servers:

  • TROIndyTCPServer, TROIndyHTTPServer --> use IndyServer.Bindings property
  • TROIndyUDPServer, TROBroadcastServer --> use IndyUDPServer.Bindings property
  • TROIpTCPServer --> use BindV6 as in TROIpSuperHTTPServer
  • TROSuperTCPServer, TROIpHTTPServer, TROWinHttpServer --> no idea, should I create two instances?

Thanks for your clarifications on this situation.

  • TROSuperTCPServer has public Server property:

property Server: TIdTCPServer read GetServer;

use Server.Bindings property

  • TROIpHTTPServer has public Server property:

property Server: TIPAsyncHTTPServer read fServer;

use Server.BindV6 property.

  • TROWinHttpServer - use OnManualBind event:
procedure TForm86.ROWinHttpServer1ManualBind(Sender: TObject);
begin
  ROWinHttpServer1.Server.AddUrl('http://+:8099/');
end;

see more about URL format at UrlPrefix Strings - Win32 apps | Microsoft Learn

Thanks for this, maybe Server could get published on TROSuperTCPServer and TROIpHTTPServer just like IndyServer is on TROIndyTCPServer, this would make it much easier to find it.

This, however, leaves me with the TROSynapseSuperTCPServer class, which is the one I use most often.

I have reviewed this case - it won’t work because TROHttpServerApiServer and TIPAsyncHTTPServer haven’t published properties.
also for TROSuperTCPServer server, it can be a bad idea - users can modify internal Indy properties (like timeouts, etc), reassign events via Object Inspector so functionality of this server can be broken.

Fair enough, but what about TROSynapseSuperTCPServer?

  TROSynapseSuperTCPServer = class(TROBaseSuperTCPServer)
  public
    property Server: TROSynapseServerSocket read GetServer;

TROSynapseServerSocket class also has no published properties

Yes, I know that, and as indicated in my initial message, I tried working with it but could not get it to bind on both stacks.
Would you have a working example you could share?

you can use only one bind per server, i.e.

  ROServer.Server.BindList.Add('::1:8096');
  ROServer.Server.Sock.RaiseExcept := True;
  ROServer.Active := true;

if you are using two values in BindList like

  ROServer.Server.BindList.Add('::1:8096');
  ROServer.Server.BindList.Add('0.0.0.0:8095');
  ROServer.Server.Sock.RaiseExcept := True;
  ROServer.Active := true;

the Synapse TCP/IP Socket error 10022: Invalid argument. error will be raised.

Note: you can use several TROSynapseSuperTCPServer instances

So the synapse server is the only one which cannot dual bind, this is a bit of a pity.