How can Indy's TIdTCPClient
and TIdTCPServer
be used in the following scenario:
Client ---------- initate connection -----------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
The client initiates the connection, but acts as a "server" (waiting for commands and executing them).
The OnExecute
approach of TIdTCPServer
does not work well in this case (at least I am not getting it to work well). How could I do this?
I hope the question is clear enough.
There is nothing preventing you from doing this with Indy's TIdTCPServer component.
A TIdTCPServer only sets up the connection. You'll need to implement the rest. So the sequence of the actual sending and receiving can be whatever you want.
Put this code in your TIdTCPServer component's OnExecute event:
var
sName: String;
begin
// Send command to client immediately after connection
AContext.Connection.Socket.WriteLn('What is your name?');
// Receive response from client
sName := AContext.Connection.Socket.ReadLn;
// Send a response to the client
AContext.Connection.Socket.WriteLn('Hello, ' + sName + '.');
AContext.Connection.Socket.WriteLn('Would you like to play a game?');
// We're done with our session
AContext.Connection.Disconnect;
end;
Here's how you can setup the TIdTCPServer really simply:
IdTCPServer1.Bindings.Clear;
IdTCPServer1.Bindings.Add.SetBinding('127.0.0.1', 8080);
IdTCPServer1.Active := True;
This tells the server to listen on the loopback address only, at port 8080. This prevents anyone outside of your computer from connecting to it.
Then, to connect your client, you can go to a Windows command prompt and type the following:
telnet 127.0.0.1 8080
Here's the output:
What is your name?
Marcus
Hello, Marcus.
Would you like to play a game?
Connection to host lost.
Don't have telnet? Here's how to install telnet client on Vista and 7.
Or with a TIdTCP Client, you can do this:
var
sPrompt: String;
sResponse: String;
begin
// Set port to connect to
IdTCPClient1.Port := 8080;
// Set host to connect to
IdTCPClient1.Host := '127.0.0.1';
// Now actually connect
IdTCPClient1.Connect;
// Read the prompt text from the server
sPrompt := IdTCPClient1.Socket.ReadLn;
// Show it to the user and ask the user to respond
sResponse := InputBox('Prompt', sPrompt, '');
// Send user's response back to server
IdTCPClient1.Socket.WriteLn(sResponse);
// Show the user the server's final message
ShowMessage(IdTCPClient1.Socket.AllData);
end;
An important thing to note here is that the ReadLn statements wait until there is data. That's the magic behind it all.