Reputation: 16620
I have a client application that should send notify messages to an optional server application. The client should not be influenced by whether the server appliction exists or not. It should try to connect to the server application and send the notify message and in case of errors it should just silently ignore all errors and continue work.
I'm using Indy for the TCP communication but all attempts to avoid error messages showing up (i.e. when ther server application closes while connected to the client) failed.
Is there a way to really make this robust?
Current code looks like this:
if (not Client.Connected) then
begin
Client.Host := ServerName;
Client.Port := ServerPort;
Client.ConnectTimeout := ConnectTimeout;
try
Client.Connect;
except
Exit;
end;
end
try
Client.IOHandler.WriteLn ('NOTIFYCHANGE "' + Param + '"');
Client.IOHandler.WriteBufferFlush;
except
try
Client.Disconnect;
except
{ ignore errors while disconnecting }
end;
try
Client.Connect;
except
{ ignore errors while connecting }
end;
end;
Upvotes: 3
Views: 870
Reputation: 17132
You don't say whether you're using Indy 9 or 10. I use 9, myself, so the below assumes this.
Why not just this?:
procedure Send(Target: String; Port: Integer; S: String);
var
C: TIdTcpClient;
begin
C := TIdTcpClient.Create(nil);
try
try
C.Host := Target;
C.Port := Port;
C.Connect;
try
C.Write(S);
finally
C.Disconnect;
end;
except
// Ignore Indy exceptions
on EIdException do;
end;
finally
C.Free;
end;
end;
It's easy enough to turn this into a procedure that uses a pre-existing TIdTcpClient.
Upvotes: 0
Reputation: 6137
For simple TCP communications task I've used Synapse package, it's not as bloated as Indy and feels "cleaner" to use.
From my recent code:
procedure SendMessage(m: string);
var
sock : TTCPBlockSocket;
response : string;
begin
Sock := TTCPBlockSocket.Create;
try
Sock.SetTimeout(200);
Sock.Connect(PrinterServerAddr, IntToStr(PrinterServerPort));
Sock.SendString(m);
response := Sock.RecvString(1000);
finally
Sock.Free;
end;
end;
..
try
SendMessage(NewMessage);
except
//..handle exception..
end;
Wrap that inside TThread if you want to avoid blocking your current thread.
Upvotes: 2
Reputation: 975
Harriv response is OK, you are describing the behaviour of an UDP connection. I'm using in a similar situation.
Upvotes: 0
Reputation: 6137
If possible, consider using UDP. It's "connectionless", so sender will just send the message and receiving application will receive it if it is listening to the port. However the sender doesn't get any confirmation about the delivery unless the server sends some kind of acknowledgement.
Upvotes: 0
Reputation: 163317
Do you really get error messages from your program? It's common that when debugging that the debugger detects exceptions and interrupts your program, and some people confuse the debugger's message for a message from their own program. Are you sure that's not the case here? I've written about this situation before. Here's the summary of ways to avoid it:
If the message really is coming from your program and not the debugger, then go back and use the debugger to figure out where the message is coming from. When the message appears, pause the program and look at the call-stack window to find the area of your code that's displaying the message, since it clearly isn't in the code you've shown. The code you've shown is thoroughly suppressing (not handling) all exceptions, even the ones that aren't related to Indy, such as EAccessViolation
and EOutOfMemory
.
Upvotes: 3