Reputation: 102
I am modifying an Indy10 TCP/IP application and I would like your suggestions/opinions/sample code on implementing a client side function that does the following
a) on application startup when the splash screen is displayed, it verifies that the client computer has internet access and the TCP Server is up and running and waiting for communication. If this is not the case, the application should terminate.
b) does (a) above before ANY data exchange between the client and the server
In addition, does the server need to repeatedly broadcast some sort of message to inform potential clients that it is up and running?
Thanks for your assistance.
Upvotes: 3
Views: 3235
Reputation: 36654
On "does the server need to repeatedly broadcast some sort of message":
There are systems (servers, services) which advertise their location (IP adress, port number) and even additional information (for example a status) to interested clients actively using IP Multicast.
It is easy to implement both server- and client side with Internet Direct (Indy) UDP components.
Here is a IP multicast example for Delphi for the open source message broker Apache ActiveMQ with full source code:
Discover ActiveMQ brokers with Delphi XE4 and Indy 10.6
Upvotes: 2
Reputation: 76713
How to verify if it's possible to connect to a TCP server ?
To your first question; definitely wrap the connection attempt to a separate thread, which you'll run when your splash screen shows. In that thread you can simply try to Connect
and catch the exception. If the exception is raised, the connection failed. If not, you were able to connect. For the notification about this state I would use custom messages, which you'll send to a splash screen form like shown in the following pseudocode:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdTCPClient;
const
WM_CONNECTION_NOTIFY = WM_USER + 1;
SC_CONNECTION_FAILURE = 0;
SC_CONNECTION_SUCCESS = 1;
type
TConnThread = class(TThread)
private
FMsgHandler: HWND;
FTCPClient: TIdTCPClient;
protected
procedure Execute; override;
public
constructor Create(const AHost: string; APort: Word; ATimeout: Integer;
AMsgHandler: HWND); reintroduce;
destructor Destroy; override;
end;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FConnThread: TConnThread;
procedure WMConnectionNotify(var AMessage: TMessage); message WM_CONNECTION_NOTIFY;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TConnThread }
constructor TConnThread.Create(const AHost: string; APort: Word;
ATimeout: Integer; AMsgHandler: HWND);
begin
inherited Create(False);
FreeOnTerminate := False;
FMsgHandler := AMsgHandler;
FTCPClient := TIdTCPClient.Create(nil);
FTCPClient.Host := AHost;
FTCPClient.Port := APort;
FTCPClient.ConnectTimeout := ATimeout;
end;
destructor TConnThread.Destroy;
begin
FTCPClient.Free;
inherited;
end;
procedure TConnThread.Execute;
begin
try
FTCPClient.Connect;
PostMessage(FMsgHandler, WM_CONNECTION_NOTIFY, 0, SC_CONNECTION_SUCCESS);
except
PostMessage(FMsgHandler, WM_CONNECTION_NOTIFY, 0, SC_CONNECTION_FAILURE);
end;
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
FConnThread := TConnThread.Create('123.4.5.6', 123, 5000, Handle);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FConnThread.Free;
end;
procedure TForm1.WMConnectionNotify(var AMessage: TMessage);
begin
case AMessage.LParam of
// the connection failed
SC_CONNECTION_FAILURE: ;
// the connection succeeded
SC_CONNECTION_SUCCESS: ;
end;
end;
end.
Does the server need to repeatedly broadcast some sort of message to inform potential clients that is running ?
No, this works in a different direction - client asks server if it's running. It's like that simply because server doesn't know clients, but client knows server.
Upvotes: 2