Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indy TCP Client/Server with the client acting as a server

Tags:

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.

like image 781
jpfollenius Avatar asked Dec 07 '11 12:12

jpfollenius


People also ask

Can a TCP server be a client?

TCP controls the accuracy of data transmission. IP, or Internet Protocol, performs the actual data transfer between different systems on the network or Internet. Using TCP binding, you can create both client and server portions of client-server systems.

What is TCP server and TCP client?

A TCP server listens on a well-known port (or IP address and port pair) and accepts connections from TCP clients. A TCP client initiates a connection request to a TCP server in order to setup a connection with the server. A real TCP server can accept multiple connections on a socket.

How would you establish a TCP connection between client and server?

Key Concept: The normal process of establishing a connection between a TCP client and server involves three steps: the client sends a SYN message; the server sends a message that combines an ACK for the client's SYN and contains the server's SYN; and then the client sends an ACK for the server's SYN.

Is TCP IP client server?

TCP/IP Client and Server ConnectionsThe “Client” in a TCP/IP connection is the computer or device that “dials the phone” and the “Server” is the computer that is “listening” for calls to come in.


1 Answers

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.

like image 151
Marcus Adams Avatar answered Sep 23 '22 20:09

Marcus Adams