Mega Code Archive

 
Categories / Delphi / Ide Indy
 

Indy Step by Step Part 2.2

Title: Indy Step by Step - Part 2.2 Question: The TIdTcpServer component Answer: Once we have finished the explanations for threading model. we will look "in deep" on the TIdTcpServer component. For now, you can look at the bellow table where the TIdTcpServer properties are explained: PropertyDetails Active When Active property is true, the server is able to handle incoming connections (is started). When it is false, the server is inactive. Command Handlers CoomandHandlers is a collection of text commands that will be processed by the server. This property greatly simplify the process of writing servers based on text protocols. CommandHandlersEnbaled When it is set to true, the server will work with defined CommandHandlers. If it is false, the entire communication will be handeled by the OnExecute event( this aspects are discussed bellow) DefaultPort Is the port that will be listened by the server. Greeting It is the Greeting message definition. MaxConnections This is the maximum number of parallel connections allowed. If this value is 0, the server will not limit the number of paralel connections. If it is greater than 0, the server will respont with MaxConnectionsReply when the no. of connections are greater than allowed no. of connections. MaxConnectionsReply The message that will be sent when a client try to connect to the server and the no. of connections is greater than the no. of allowed connections ReplyUnnknownCommand This message is send to the client when the client try to execute an inexistent command. The CommandHandlersEnabled property must be true. If it is set to false, this property is ignored. TerminateWaitTime This is the no. of miliseconds that the server should wait to terminate active threads(when you stop the server). This properties are the most important. You will work whith them every time when you will create servers. As you have saw, you are able to work with indy servers using 2 modes. First mode is with CommandHandlers. This mode greatly simplifies the mode you develop a text based protocol. Let me explain a little bit using an example: Let's develop a server that implements 2 commands: hello and add. When a client send a hello command the server simply will respond with "Hi!". The add command is little different, because it can have many parameters and the server will respond with the sum of the parameters passed by this command. The format we will use for this command is: add no1 no2 ... noN and the server will respond with: no1+no2+...+noN (the sum of all numbers) Now we will implement this server. Put a TIdTCPServer on the form set it's active property to true, Default port to 1111 and CommandHandlesEnabled to true. Now, open the collection editor of the CommandHandlers and add 2 new items. For first item fill the Command property with the name of our first command (Hello). Also, for this command set the ReplyNormal Text property with the response text ("HI!"). Now the first command is implemented. For the second item fill the Command property with "add". It is time to write a little code... In the ObjectInspector click on the events tab and doubleclick on the OnCommand item. And now, the coding part: procedure TForm1.IdTCPServer1CommandHandlers1Command(ASender: TIdCommand); var i:integer; f:float; begin f:=0; for i:=0 to ASender.Params.Count-1 do f:=f+strtofloat(ASender.Params[i]); ASender.Thread.Connection.Writeln(floattostr(f)); end; ...And that's all folks! Test your server with the telnet program and you will see thats all works fine. I know that we haven't implement an error handling procedure, but for our scope this example is almost sufficient. Looking on the code we have writed you will observer the following: 1. We have a strange ASender property 2. We have for this ASender some properties like Params and Connection 3. In the final, for sending a string over a TCP/IP connection we are using the Writeln method of the connection property. Seems to be simple.The strange ASender is our client connected. Remember our discussion about indy threads? For each client connected to the server a new thread is created. In our case, the ASender property represent our client. ASender property has many properties, but the most important is the Connection property that represent, as you maybe imagine, our connection with the client. Over this connection, we can send Strings, Integer Values, records etc. In fact, using methods defined for Connection property you can send, in fact, any data. In the table bellow you have all methods used for communicating with client. Property Details Write Write a string. Similar to write for files Read Read a string. Similar with read for files. WriteLn Write a string with terminator. Similar with Writeln for files ReadCardinal(AConvert:boolean) Read a cardinal(32 bit unsigned) value. If AConvert is true, the value is converted to Internet Byte order from the Native Intel Byte order. If not, no connevrsion is done WriteCardinal(AValue:Cardinal;AConvert:boolean) Write a cardinal(32 bit unsigned) value. If AConvert is true, the value is converted to Internet Byte order from the Native Intel Byte order. If not, no connevrsion is done ReadInteger(AConvert:boolean) Read an integer value. If AConvert is true, the value will be converted from Internet to Intel byte-order. WriteInteger(AValue:integer; AConvert:boolean) Write an integer value. If AConvert is true, the value will be converted from Internet to Intel byte-order. ReadBuffer(ABuffer;AByteCount:longint) Read a buffer. ABuffer is the buffer we want to read and AByteCount is the size of the buffer we are reading. WriteBuffer(ABuffer;AByteCount:longint; AWriteNow:boolean) Send a buffer to the peer . ABuffer is the buffer we want to read and AByteCount is the size of the buffer we are reading. AWriteNow is a boolean value thats indicate if the data contained in buffer will be writed imediatly, ignoring indy buffering mechanism. By default this value is false. ReadStream (AStream:TStream;AByteCount:longint;AReadUntilDisconnect:boolean) Read a stream. AStream is the stream we want to read and AByteCount is the size of the stream we are reading. Default value for AByteCount is -1. AReadUntilDisconnect is a boolean value. If it is set tu true the stream will be readed until the connected property will be set to false (when disconnected the reading of the stream will be done). WriteStream (AStream:TStream;AAll:boolean;AWriteByteCount:boolean) Write a stream. AStream is the stream we want to send. When AAll is true, the stream will be writed from it's begining. When is set to false, the stream will be writed from it's current position. When AWriteByteCount is set to true, the size of the stream will be send to the peer connection. When it is false, the size of the stream will not be send. These are the most important methods of the Connection property. You will use these methods every time when you will create servers or clients. And, most important, you have to know what each method does. When I have saw for the first time the indy architecture, my mind was gone to the dos time. Remember how looks a program writed in Turbo Pascal? Let's see: program Sum; var a, b: real; begin Write('A='); ReadLn(A); Write('B='); Readln(B); a:=a+b; Write ('The Sum is:'); Writeln(a); end. I was surprised when I have discovered indy. It's programming maneer is the same, but the results are great. You can observe the elegance of indy by creating any TCP/Ip enabled Client/Server applications. In the next episode, we will discuss a little about TIdTcpClient component and then will follow practical examples. Stay with Indy!