In Socket applications programmed by TCPServer/Client components, usually we active server side, then connect client to server, and when we need to get or send data from one side to other, first we send a command from client to server and a communication will starts.
But the problem is that always we need to start conversation from client side!
I want to ask is any idea for start conversation randomly from server side without client side request?
I need this functionality for notify client(s) from server side. for example, when a registered user (client-side) connected to server, other connected users (on other client-sides), a notification must send from server to all users (like Yahoo Messenger).
I'm using TIdCmdTCPServer and TIdTCPClient components
You are using TIdCmdTCPServer
. By definition, it sends responses to client-issued commands. For what you are asking, you should use TIdTCPServer
instead, then you can do whatever you want in the TIdTCPServer.OnExecute
event.
What you ask for is doable, but its implementation depends on your particular needs for your protocol.
If you just want to send unsolicited server-to-client messages, and never responses to client-to-server commands, then the implementation is fairly straight forward. Use TIdContext.Connection.IOHandler
when needed. You can loop through existing clients in the TIdTCPServer.Contexts
list, such as inside the TIdTCPServer.OnConnect
and TIdTCPServer.OnDisconnect
events. On the client side, you need a timer or thread to check for server messages periodically. Look at TIdCmdTCPClient
and TIdTelnet
for examples of that.
But if you need to mix both client-to-server commands and unsolicited server-to-client messages on the same connection, you have to design your protocol to work asynchronously, which makes the implementation more complex. Unsolicited server messages can appear at anytime, even before the response to a client command. Commands need to include a value that is echoed in the response so clients can match up responses, and the packets need to be able to differentiate between a response and an unsolicited message. You also have to give each client its own outbound queue on the server side. You can use the TIdContext.Data
property for that. You can then add server messages to the queue when needed, and have the OnExecute
event send the queue periodically when it is not doing anything else. You still need a timer/thread on the client side, and it needs to handle both responses to client commands and unsolicited server messages, so you can't use TIdConnection.SendCmd()
or related methods, as it won't know what it will end up reading.
I have posted examples of both approaches in the Embarcadero and Indy forums many times before.