Introduction to Indy. Developing client-server applications using Indy in Delphi

Indy components used in Delphi 6.

In addition to basic Internet services and protocols, there is a wide range of additional services, the capabilities of which are often used by Internet developers. In addition, the ability to display information using a browser is not always an acceptable solution for Internet applications. In this case, it is reasonable to use the Internet infrastructure for data exchange, and provide information display through more complex client applications developed, for example, in Delphi.

Let's say you need to implement specialized server logic that is not included in standard Web servers. To solve this class of problems, Delphi includes the Internet Direct (Indy) library from Nevrona Designs (http://www.nevrona.com/Indy/). This library, developed specifically for Borland Delphi, already has eight versions, the latest of which is included in new version Delphi. The set of components is divided into three groups: client (Indy Client), server (Indy Servers) and auxiliary (Indy Misc).

Indy Clients and Indy Server s

Most Indy Client and Indy Servers components are pairs corresponding to the client and server parts of the protocols and services (with the exception of certain, mainly server, components such as TunnelMaster and TunnelSlave), and allow the use of protocols such as TCP/IP, UDP, NNTP, SMTP, FTP, HTTP, as well as services ECHO, FINGER, WHOIS, etc.

Indy client components are written using sockets. The client side socket requires a connection to the server. If the connection is established, the client and server can begin exchanging messages. These messages are of a different nature, but usually the exchange occurs using a specific protocol (for example, HTTP)

TIdTCPClient and TIdTCPServer

These components are used to support one of the main network protocols - TCP (Transmission Control Protocol), and are also the base classes for the TIdSMTP and TIdFTP components. The TIdTCPServer class has a ThreadMgr property that defaults to nil. If ThreadMgr is nil when TIdTCPServer is enabled, the TIdThreadMgrDeafault class will be created implicitly. Otherwise, the installed process manager is used.

TIdUDPClient and TIdUDPServer

These components are used to support network protocol UDP (User Datagram Protocol) and are also the base classes for a number of other Indy components.

TIdChargenServer

The component is used to generate random symbols, usually for testing purposes.

TIdDayTime and TIdDayTimeServer

The components are used to provide time service. The client requests, and the server reports the current date and time.

TIdDNSResolver

This is a client component that serves requests from a DNS (Domain Name Service) server. DNS server queries are designed to replace a computer's name with its IP address. TIdDNSResolver is a descendant of the TIdUDPClient class.

TIdDICTServer

A server component that supports the Dictionary Server Protocol (DICT), a server-side dictionary based on the TCP protocol that allows a client to access a natural language dictionary.

TIdDISCARDServer

The server component that supports the records server. The recordings can be used as a debugging and measurement tool. The records service simply hands over any data to whoever is willing to receive it.

TI dEcho and TI dECHOServer

The components are designed to provide a response service, typically used to check the health of the network. The client sends a text message to the server, the server returns the message to the client. If the message is garbled, the network malfunctions.

TIdFinger and TIdFingerServer

The components are designed to provide a protocol that allows a user to query data regarding the presence of other users on the system. Some servers handle such client requests. Using this pair of components will allow you to service client requests that determine the presence of other users on the system.

The component includes full support for the file transfer protocol - FTP (File Transfer Protocol). Passive and active data transfer is supported, as well as operations such as GET and PUT, deleting directories, obtaining quotas, file and directory sizes. TI dFTP uses the TIdSimpleServer class to operate. When an FTP file transfer is in progress, a secondary TCP connection is opened for data transfer and is closed when the data has been transferred. This connection is called a "data link", unique for each file being transferred.

TIdGopher and TIdGopherServer

These components are designed to provide a network protocol that has been superseded in Lately from WWW (World Wide Web) HTTP protocol. The server that implements this protocol provides a hierarchical distributed document flow support system. An example of the use of this pair of components, located in the demosindyGopherClient and demosindy GopherServer directory, demonstrates how this protocol can be used to provide local network information about files located on your computer, including closed ones.

TIdHostNameServer

A server component designed to pass the local server name to clients.

TIdHTTP and TIdHTTPServer

The components are used to provide the HTTP network protocol (versions 1.0 and 1.1 are supported, including GET, POST and HEAD operations). In addition, support is provided for authentication and the use of proxy servers. The server component is used to provide services to another Web server that supports a given protocol. TIdHTTPServer facilitates the implementation of functions such as cookies, state management, etc.

TIdIcmpClient

A client component designed to provide the Internet Control Message Protocol (ICMP), which is used to perform ping operations and network tracing.

A client component designed to provide the Post Office Protocol (POP), including support for MIME encoding and decoding, and multibyte character transmission.

TIdIMAP4Server

A server component designed to support IMAP (Internet Message Access Protocol) operations on the server. The protocol allows you to search for messages Email on server. The difference between the IMAP and POP protocols is that the POP protocol requires additional memory to store data, and the IMAP protocol accesses the server instead of the client machine. IMAP4 was created to replace POP3, but POP3 remains a widely used standard to this day.

TIdIRCServer

A server component designed to support the most commonly used service operations on the Internet, commonly called chat. The component provides basic building blocks for IRC (Internet Relay Chat) server.

TIdMappedPortTCP

A server component designed to create mapped ports, which are often used in proxy servers. The methods of this component allow you to map one port to another. For example, port 80 could be mapped to port 3000, and all requests to the first port (port 80) would be forwarded to the second port (port 3000).

TIdNNTP and TIdNNTPServer

These components are required to support the Network News Transfer Protocol (NNTP) used in news services. The client component includes support for MIME encoding and decoding, as well as support for multibyte characters and alternate encodings. The server component allows you to create news servers. It is important to note that TIdNNTPServer is not a full-featured news server, but a component that provides the basic functionality for such a server.

TIdQOTD and TIdQOTDServer

The components are used to provide the Quote of the Day service. The client component connects to the server component instance to obtain the daily quote. Each server instance contains a unique citation database.

A client component designed for use in Simple Mail Transfer Protocol (SMTP) applications, providing support for authentication, MIME encoding and decoding, and multi-byte character support.

A client component designed to provide SNTP (Simple Network Time Protocol) - a time service. Can be used to connect to any time service to determine the current date and time.

TIdSimpleServer

Server component that provides a lightweight TCP server. Allows you to organize a point-to-point connection. It is used to create servers with a single user, that is, it can only serve one connection at a time. Unlike the TIdTCPServer component, it does not spawn secondary processes when waiting for requests from clients and when processing these requests. In other words, if the server is serving a request from a client, and at that time another client is contacting it to connect, then it will be blocked until the end of processing the first request.

TIdTelnet and TIdTelnetServer

The client component is used to organize remote sessions on another computer, including console negotiations and authentication. The communication protocol assumes the presence of a person interacting interactively with the server. The client component does not have display support or terminal emulation, but simply provides a connection to the server part. Typically, the TIdTelnetServer server protocol is used to organize remote databases with a text interface for interactive interaction with clients.

TIdTime and TIdTimeServer

The client component is an alternative to the TIdSNTP component for determining time. It is important to note that the formats of the two protocols are different. TIdTime is based on the RFC 868 format (returns the time in the internal UNIX OS standard, performing all necessary conversions). The server component is similar in functioning to the DayTime server. Can be used to implement a time service on local computer. No additional code is required, just create an instance of TIdTimeServer that will return the time of the server computer's internal clock.

TIdTrivialFTP and TIdTrivialFTPServer

These components are necessary to organize a simple file transfer protocol. The client component of this protocol is used to connect to an instance of the corresponding server component. The protocol is intended for private, lightweight, local cases of file transfer, for example in local area networks or for loading (uploading) routing tables into routers. Due to the weakened characteristics of this protocol, its use is not recommended when using authentication algorithms or any other security mechanisms. The main purpose of this protocol is to transfer files to a hardware device for the purpose of modifying it.

TIdTunnelMaster and TIdTunnelSlave

Server tunnel components are used in proxy servers to organize multiple logical connections over one physical (tunnel). These classes can be used for various purposes, for example, to organize a secret connection over non-secret channels.

TIdWhois and TIdWhoIsServer

This client component connects to any standard Whois server, allowing you to obtain information about domains. The server component provides the basic functionality of a NIC server.

Indy Misc

The Indy Miscellaneous Components palette page includes BASE64, UUE, Quoted Printable and other common email communication formats, encoders (MD2, MD4 and MD5) for cryptography standards used to store passwords and electronic signatures in an irreversible (hard to decipher) form, as well as many other useful components and utilities often used in the development of Internet applications.

TIdAntiFreeze

Due to the block-based algorithms of Indy components, it often appears that the application is stuck while the connection is working. To eliminate the use of secondary processes (threads) when organizing communications to prevent the application from freezing, it is enough to place the specified component on the form.

The component works by parsing requests from the TCP/IP protocol stack and sending messages to the application during the delay when external connections are blocked, which creates the illusion of running code. Since the component affects blocked connections only for the main process, the use of TIdAntiFreeze in secondary processes of the application is not required. Be aware that the TIdAntiFreeze component slows down connections because the main process is periodically interrupted to process messages. It follows that care must be taken to ensure that the application being developed does not spend too much time processing messages, including OnClick, OnPaint, OnResize, etc. To some extent, this can be controlled through the properties of the TIdAntiFreeze class. The use of this component is not mandatory, but it allows you to solve the problem of synchronizing connections with the visual interface of the application.

TIdDateTimeStamp

A class for performing date and time math related to the fact that Internet protocols use different date and time formats; in addition, clients and servers may be located in different time zones.

TIdIPWatch

It is a timer-based component that constantly monitors changes in the computer's IP address. Component events occur when a change is detected. This component is usually used to detect whether a computer is connected to the Internet or any other network. The change in IP address in this situation may occur due to the IP address being assigned by the DHCP (Dynamic Host Configuration Protocol) server when connecting to the new network.

TIdLogDebug

The purpose of this component is to intercept events of any client or server component and place a record of the event in specified file. This component is very useful for debugging Indy components.

TIdMessage

The component is used in combination with other components to properly decrypt or encode messages. These can be POP, SMTP and NNTP components. The class supports MIME encryption and decryption, multibyte characters, and ISO encoding.

TIdNetworkCalculator

One of the few Indy components that can be used when building applications. The network calculator can be used to perform calculations on IP addresses, including network masks, subnet, network classes, etc.

TIdThreadMgrDefault

The component provides control of secondary processes by default. Created when any Indy component that supports process management does not have an instance of the TIdThreadManager class defined. The component provides only basic capabilities for managing secondary processes: creating and destroying them on demand.

TIdThreadMgrPool

A more advanced process management component than TIdThreadMgrDefault because it merges processes rather than creating or destroying them on demand.

TIdVCard

VCard is the electronic equivalent of a business card and may contain the owner’s personal information and graphic data.

TIdIMFDecoder

Designed for decoding Internet messages. It is a descendant of the TIdCoder class, just like all other encoder components. The TIdCoder class decodes according to the ARPA Internet text message format standard RFS-822, proposed in August 1982, and the USENET messaging standard RFC 1036, proposed in December 1987.

The component extends the TIdCoder class to allow detection of RFS-822 format by header context, providing decrypt-on-receive mode and MIME encryption and decryption. The TIdIMFDecoder component is used in the TIdMessageClient class to decode received and transmitted messages.

TIdQuotedPrintableEncoder

QuotedPrintableEncoder allows you to decrypt text in the specified format. Can serve as a standalone component with a specified encoding type, allowing messages containing a new encoding type to be transmitted.

TIdBase64Encoder

Implements another encryption algorithm that makes it possible to transmit non-printable characters.

TIdUUEncoder

Implements one of the first encryption algorithms, UU encoding. Sometimes used when mailing articles to a news service.

TIdXXEncoder

This encryption method is unlikely to ever be used. Essentially, this is the same UU encoding, but with a different encryption table.

TIdCoderMD2

Components with different types of MD (Message Digest) encryption algorithm. They are all shuffle-based, one-way, and have no decryption algorithms.

Components of protocol clients and servers can be used to develop server and client Internet applications, together with or instead of basic ones (ClientSocket, ServerSocket) and other components from the Internet and Fastnet palette. Indy components do not use the WebBroker architecture, implementing low-level support for Internet protocols and services directly in their source code (source codes included).

TIdConnectionInterceptOpenSSL and TIdServerInterceptOpenSSL

The SSL protocol - Secure Sockets Layer, which ensures the secrecy and reliability of communication between two applications, has two layers. At the low level of a multi-layer transport protocol (such as TCP), SSL is a recording protocol and is used to encapsulate various higher-level protocols. The advantage of SSL is that it is an independent application protocol, but a higher-level protocol can be used on top of SSL.

SSL provides communication security, which has three main functions: providing a confidential connection; encryption with public key(used to confirm the authenticity of the addressee); support for data transmission reliability.

  • Symmetric cryptography is used to encrypt data (eg DES, RC4, etc.).
  • Digital signature is provided using asymmetric public key encryption (for example, RSA, DSS, etc.).
  • Reliability of communication, message transport includes checking the integrity of the message through MAC correction codes, secure hash functions (eg, SHA, MD5, etc.) using MAC calculations.

Combined with HTTP and server authentication, SSL provides necessary functions encryption and further maintains the established connection, double-checking the authenticity of the Web server, etc. It is important to understand that SSL only protects communications during data transfer and does not replace other security mechanisms.

The TIdConnectionInterceptOpenSSL and TIdServerInterceptOpenSSL components provide both client-side and server-side connections using the SSL protocol. It should be noted that the TIdConnectionInterceptOpenSSL and TIdServerInterceptOpenSSL components are only available in Delphi 6, and not in Kylix. This is due to the complexity of the protocol, which in the case of a Windows implementation is based on operating system functions.

Examples of using Indy components can be found in the /Delphi6/Demos/Indy directories. In total, the Indy library in version 8.0 contains 69 components. It is stated that in version 9.0 the specified library will contain 86 components. All components are unified and included in both Delphi 6 and Kylix, which allows them to be used for developing cross-platform applications. All Indy components support multithreading.

The Indy components implement almost all the functionality found in the Internet and Fastnet components, as is clearly shown in the table.

Fastn et components Indy components Purpose of components
1 TserverSocket, TClientSocket TIdTCPserverSocket, TIdTCPClientSocket Interaction between two computers (client and server) using the TCP/IP protocol
2 TNMDayTime TIdDayTime, TIdDayTimeServer Query the server for the current time
3 TNMEcho TIdEcho, TIdEchoServer Used to communicate with the response server
4 TNMFinger TIdFinger, TIdFingerServer Used to obtain information about the user from an Internet search server
5 TNMFTP TIdFTP, TIdTrivialFTP, TIdTrivialFTPServer Provide file transfer using FTP protocol
6 TNMHTTP TIdHTTP, TIdHTTPServer Use HTTP protocol for data exchange
7 TNMMsgServ, TNMMsg Used to convey simple text messages from client to server
8 TNMNNTP TIdNNTP, TIdNNTPServer Supports data exchange with news server
9 TNMPOP3 TIdPOP3 Used to receive email from a mail server using the POP3 protocol
10 TNMSMTP TIdSMTP Used to send email via mail server Internet
11 TNMStrm, TNMStrmServ Transmits binary data written to a stream using the TCP/IP protocol
12 TNMUDP TIdUDP, TIdUDPServer Transfer data using the UDP protocol
13 TpowerSock, TNMGeneralServer Component-encapsulated classes that are the basis for writing your own clients (Powersock) and servers (NMGeneralServer)
14 TNMUUProcessor TIdUUEncoder, TIdUUDecoder Carry out recoding binary files to MIME or UUENCODE format
15 TNMURL Converts strings to HTML format and performs reverse conversion

The exceptions are classes such as TNMMsgServ, TNMMsg, TNMStrm, TNMStrmServ, TpowerSock, TNMGeneralServer, TNMURL, which either implement obsolete protocols or have functionality implemented in a large group of alternative classes.

However, unlike its predecessors - the Internet and Fastnet components, Indy contains richer server components and components for data transcoding and encryption, as well as authentication support (Indy Misc palette). As can be seen from the table above, the main protocols and services are provided not only by client, but also by server components. These are time services, response services, obtaining user information, as well as HTTP, NNTP, UDP protocols and even the simplest version of FTP.

Some examples of using Indy components

In Indy components contained in Delphi, the IP address is defined in the Host property, typically only in client applications. Server-hosted components have methods that allow you to start or stop polling the corresponding port - for example, changing the Active property of the IdTCPServer component starts or stops polling the corresponding port. Once the connection between the client and server is established, data transfer can begin.

Indy components place great emphasis on security and reliability when working with data. For example, the IdTCPClient component has Connect and Disconnect methods. Using a programming technique like the below code from the client side:

With TCPClient do begin Connect; try lstMain.Items.Add(ReadLn); finally Disconnect; end; end;

and using the Connection property passed as a parameter to the AThread instance of the TIdPeerThread class from the server side:

With AThread.Connection do begin WriteLn("Hello from Basic Indy Server server."); Disconnect; end;

you can count on either the normal execution of the connection or the correct error handling.

Note the ReadLn and WriteLn methods of the corresponding classes - they resemble standard Pascal I/O statements. This is a tribute to the UNIX programming technique, where most system operations are performed by reading and writing to the corresponding files.

Just like Fastnet components, Indy component classes have events that can be used to provide event management. For example, you can arrange for a message to be displayed on a form when connecting to a client:

Procedure TForm1.IdECHOServer1Connect(AThread: TIdPeerThread); begin lblStatus.caption:= "[ Serving client ]"; end;

Indy provides components that implement protocols with client and server parts that are unique to this library. The TIdGopherServer and TIdGopher components, thanks to the GetExtendedMenu, GetFile, GetMenu, GetTextFile methods on the client side and ReturnGopherItem, SendDirectoryEntry on the server side, help to view files various types, including those marked as hidden, as well as directories on remote computer(similar to what the dir *.* command does in operating system MS-DOS).

Using the IdSMTP and IdMessage components, you can easily create your own Web application that can send mail using the SMTP protocol.

In this case, the IdMessage class (one of 23 components from the Indy Misc page) is responsible for generating the message, which follows from its name, and IdSMTP is for organizing the connection with the mail server.

The technology used in Indy uses locking read and write operations. Any Connect operation used in Indy waits for the connection to complete. When working with Indy client components, you typically need to do the following:

  • request a connection to the server;
  • make read and write requests to the server (depending on the type of server, the step is performed once or repeated many times);
  • end the connection to the server and disconnect.

Indy components are designed to provide an ultra-high level of abstraction. The intricacies and details of the TCP/IP stack are hidden from the programmer so that he can focus on the task at hand.

The following small example shows a typical client bean session:

With IndyClient do begin Host:= "zip.pbe.com"; // Host to call Port:= 6000; // Port to call the server on Connect; try // Your code goes here finally Disconnect; end; end;

In the example, even if the connection to the server is not established, the connection will be gracefully terminated due to the use of the try-finally statement.

Indy's server components describe a variety of server models that can be used depending on your needs and the protocol you're using.

TIdTCPServer is the most commonly used server component, which creates a secondary process independent of the main application process. The created process waits for incoming requests from potential clients. An individual secondary process is created for each client whose request it responds to. Events that occur during the maintenance process are related to the context of the corresponding processes.

In other words, for each client connection, the TIdTCPServer class uses a unique secondary thread by calling that thread's OnExecute event handler. The formal parameter of the OnExecute method is a reference to an instance of the Athread class corresponding to the created thread. The Connection property of this class is a reference to the TIdTCPConnection class, an instance of which is created to process the client request. TIdTCPConnection supports reading and writing over the connection, as well as establishing and terminating a communication session.

The UDP protocol works without first establishing a connection with the server (each sent packet is an independent set of data, and not part of a larger session or connection). While TIdTCPServer spawns separate threads for each connection, TIdUDPServer uses either a main thread or a single secondary thread that handles all UDP protocol requests. When TIdUDPServer is active, a thread is created to listen for incoming UDP packets. For each packet received, an OnUDPRead event is raised either on the main thread or in the context of the listening thread, depending on the value of the ThreadedEvent property. When ThreadedEvent evaluates to False, the event occurs on the main thread, otherwise it occurs on the listening thread. While the event is being processed, other server operations are blocked. Therefore, it is important to ensure that OnUDPRead procedures run as quickly as possible.

If you need to create a new client application for an existing server using an existing protocol, your job is solely to develop and debug the client application. However, when we have to develop both client and server applications using an existing or new protocol, we are faced with the classic "chicken and egg" problem. Where to start programming - from the client or from the server?

Obviously, both the client and the server must be created eventually. For many applications, especially those using a text-based protocol (such as HTTP), it is easier to start building the application by designing the server. And for debugging there is a convenient client that already exists. This is a Telnet console application that is available on both Windows and UNIX.

If you type the console telnet command 127.0.0.1 80 with the IP address of the local computer and port number 80, which is used by default by Web servers, then the application will respond with the text shown in Fig. 6, in case of Windows 2000 OS and IIS 5.0.

To create the simplest server using Indy components you need:

If you need to design a server that will not only correctly inform its clients when the connection is lost, but also provide them with information about error situations that have occurred, use the try-except statement instead of try-finally - for example, as shown in the following example:

Procedure TDataModule1.IdTCPServer1Execute(AThread: IdPeerThread); var s: String; begin with AThread.Connection do try try s:= ReadLn; // Perform the task of the server here // if no exception is raised, // write out the server's response WriteLn(s); except on e: Exception do begin WriteLn(e.Message); end; //on end; //try except finally Disconnect; end; end;

This small example demonstrates the steps to create a simple text server, as well as how to debug it.

The server described above is a typical example of the organization of modern distributed computing.

Features of creating multi-tier applications

Recently, multiple servers are increasingly being used to satisfy client requests. A server of this type, having received a client request and partially prepared it for further processing, contacts another server and sends it the transformed request or requests. The second-tier server can, in turn, communicate with other servers. Thus, we can talk about a multi-tier server architecture.

Next we will create a data access server whose purpose is to return data from the database. This server, however, does not read or write to the database files directly. Instead, it communicates with the database server in search of the data required by the client.

So, we start developing an application with a three-tier architecture. To create a database server using Indy components you need:

  1. Create a new project.
  2. Place on main form project instance of the TIdTCPServer component from the Indy Servers palette.
  3. Set the DefaultPort property of the TIdTCPServer1 class instance to 6001 (it is recommended to assign large values ​​to avoid duplicating port numbers across different applications), and set the Active property to true.
  4. Add a new module to the project by selecting the File | New | Data Module, and place instances of the SQLConnection and SQLDataSet components on it from the dbExpress tab on the components palette.
  5. Set the ConnectionName property of the SQLConnection class to IBLocal and LoginPrompt to False. If you have not configured IBLocal on the employee.gdb database, complete this procedure first.

Introduction to Indy

Introduction to Indy
Posted by Chad Z. Hower
Homepage: http://www.atozedsoftware.com
Translation: Anatoly Podgoretsky
introduction
I wrote this article when current version was Indy 8.0. Much of this article is applicable and very useful in future versions of Indy. If you liked this article and want to read more in-depth articles, then check out the book Indy in Depth.
Indy is running in blocking mode
Indy uses blocking sockets. Blocking mode is similar to file read-write. When reading or writing data, the function does not return control until the operation is completed. The difference from working with files is that the call may take longer, since the requested data does not yet exist, this depends on the speed at which your network or modem operates.
For example, a method is simply called and waits until control is returned to the call point. If the call was successful, control will be returned from the method; if an error occurs, an exception will be raised.
Lockdown is not fatal
Because of the blocking mode, we have been beaten many times by our opponents, but the blocking mode is not the devil.
The problem appeared after porting Winsock to Windows. In Unix, the problem was typically solved by forking (similar to multi-threading, but with separate processes instead of threads). Unix clients and daemons had to fork the processes that should be running and use blocking mode. Windows 3.x could not be parallelized and did not support much threading. Using a blocking interface froze the user interface and made programs unresponsive. Therefore, non-blocking modes were added to WinSock, allowing Windows 3.x with its limitations to use Winsock without blocking the main and only thread of the program. This required different programming, and Microsoft and others passionately vilified blocking modes to cover up the shortcomings of Windows 3.x.
Then came Win32, which was able to support multi-threading. But by this time, their brains were already muddled (that is, the developers considered blocking sockets to be the creation of the devil), and it was already difficult to change what they had done. Therefore, the vilification of blocking regimes continues.
In reality, Unix only has blocking sockets. Blocking sockets also have their advantages and are much better for multi-threading, security and other aspects. Some extensions have been added to Unix for non-blocking sockets. However, they work very differently than on Windows. They are also non-standard and not very common. Blocking sockets in Unix are used in almost all cases, and will continue to be used.
Advantages of blocking mode·Easier to program - Blocking modes are easier to program. All user code can be in one place and executed in a natural, sequential order. ·Easier to port to Unix - Since Unix uses blocking sockets, portable code is easier to write in this case. Indy uses this fact to write uniform code. ·It is more convenient to work with threads - Since blocking sockets have a sequence acquired by heredity, so they are very easy to use in threads.
Disadvantages of blocking mode · The user interface freezes in clients - A blocking socket call does not return control until it has completed its task. When such a call is made on the application's main thread, the application cannot process user messages. This causes the user interface to freeze, windows not to refresh, and no other messages to be processed until control is returned from the blocking socket.
TIdAntiFreeze component
Indy has a special component that solves the freezing problem user interface. Simply add one TIdAntiFreeze component anywhere in your application and you can make blocking calls without freezing the UI.
TIdAntiFreeze runs on an internal timer outside the call stack and calls Application.ProcessMessages when the timeout expires. External calls to Indy continue to be blocking and therefore work exactly the same as without using the TIdAntiFreeze component. Using TIdAntiFreeze allows you to get all the advantages of blocking sockets, without any of the disadvantages.
Code threads (Threading)
With blocking sockets, code streams are almost always used. Non-blocking sockets can also use threads, but this requires some additional processing and their advantages in this case are lost compared to blocking sockets.
Advantages of threads·Setting priorities - The priorities of individual threads can be configured. This allows individual tasks to be allocated more or less CPU time. ·Encapsulation - Each connection can contain some semblance of an interface with another connection. ·Security - Each thread can have different security attributes. ·Multiple processors - provides an advantage on systems with multiple processors. ·No need for serialization - provides full concurrency. Without much threading, all requests must be processed in one thread. Therefore, each task must be broken down into small chunks so that it can work quickly. While one block is running, everyone else is forced to wait for it to finish. At the end of one block, the next one is executed and so on. With multithreading, each task can be programmed as a single unit and the operating system distributes time among all tasks.
Poll threads
Creating and destroying threads is very resource intensive. This is a particularly difficult task for servers that have short-lived connections. Each server creates a thread, uses it for a short time, and then destroys it. This results in threads being created and deleted very frequently. An example of this is a Web server. A single request is sent and a simple response is returned. When using a browser, hundreds of connections and disconnections can occur when viewing any website.
Polling threads can correct this situation. Instead of creating and destroying threads on demand, threads are selected from a list of unused but already created threads from the pool. When a thread is no longer needed, it is returned to the pool instead of being destroyed. Threads in the pool are marked as unused and therefore do not consume CPU time. For even greater improvement, threads can dynamically adapt to the current needs of the system.
Indy supports thread polling. The thread pool in Indy is accessible through the TIdThreadMgrPool component.
Lots of threads
A heavily loaded server may require hundreds or even thousands of threads. There is a common belief that hundreds and thousands of threads can kill your system. This is a false belief.
In most servers, threads wait for data. While waiting on a blocking call, the thread is inactive. In a server with 500 threads, only 50 can be active at the same time.
The number of threads that are running on your system may surprise you. With a minimum number of running servers and the specified running applications my system has 333 threads created, even with 333 threads the CPU is only 1% loaded. Heavily loaded IIS server(Microsoft Internet Information Server) can create hundreds and thousands of threads.
Threads and global sections
With multiple threads, you must ensure data integrity when accessing it. This may be difficult for programmers who have not worked with threads. But in general, most servers do not need to use global data. Most servers perform isolated functions. Each thread performs its own isolated task. Global read/write sections are a feature of many multithreaded applications, but are not typical for servers.
Methodology Indy
Indy is different from other Winsock components you are used to. If you have worked with other components, then the best solution will forget how they work. Many other components use non-blocking (asynchronous) calls and operate asynchronously. They need to react to events, create a state machine, and execute frequent wait loops.
For example, with other components, when you call a connection you must either wait for the connection event to occur or wait in a loop for a property to indicate that the connection has occurred. With Indy, you can call the Connect method and wait for it to return. A refund will be issued if the connection is successful or an exception is raised if there is a problem. Therefore, working with Indy is very similar to working with files. Indy allows you to put all your code in one place, instead of spreading it across different events. In addition, Indy is very simple and most convenient when working with threads.
How different is Indy?
Brief overview · Blocking calls are used · Not event-oriented - there are events, but they are used for informational needs, and are not really required. ·Designed for Threads - Indy is designed for threads, but can be used without threads. Sequential programming
Detailed review
Indy not only uses blocking calls (synchronous) but also works like this. A typical Indy session looks like this:
with IndyClient do begin
Connect; Try
//Do your stuff here
finally Disconnect; end;
end;
With other components it looks like this:
procedure TFormMain.TestOnClick(Sender: TComponent);
begin
with SocketComponent do begin
Connect; try
while not Connected do begin
if IsError then begin
Abort;
end;

OutData:= "Data To send";
while length(OutData) > 0 do begin
Application.ProcessMessages;
end;
finally Disconnect; end;
end;
end;
procedure TFormMain.OnConnectError;
begin
IsError:= True;
end;
procedure TFormMain.OnRead;
var
i: Integer;
begin
i:= SocketComponent.Send(OutData);
OutData:= Copy(OutData, i + 1, MaxInt);
end;
Many components don't do a very good job of isolating the programmer from the stack. Many components, instead of isolating the user from the complexities of the stack, simply leave the user to it or provide a wrapper over the stack.
Indy special way
Indy is designed from the ground up to be multi-threaded. Building servers and clients in Indy is similar to building servers and clients in Unix. Unix applications typically call the stack directly with little or no abstraction layer.
Typically, Unix servers have one or more listening processes that monitor incoming client requests. For each client that needs to be served, a new process. This makes programming simple, each process for only one client. Each process runs in its own security context, which is set by the listening process or process based on existing rights, identity, or other things.
Indy servers work in much the same way. Windows, unlike Unix, cannot multiply processes well, but it works well with threads. Indy servers create a separate thread for each client connection.
Indy servers assign a listening thread that is separate from the program's main code thread. The listening thread listens for incoming requests from clients. For each client it responds to, a new thread is created to serve the client. Relevant events are then serviced in context of this stream.
Indy Customer Review
Indy is designed to provide a very high level of abstraction. The intricacy and detail of the TCP/IP stack is hidden from the programmer. Typically, a typical client session in Indy looks like this:
with IndyClient do begin
Host:= "zip.pbe.com"; // Host to call
Port:= 6000; // Port to call the server on
Connect; Try
//Do your stuff here
finally Disconnect; end;
end;
Indy server overview
Indy server components create a listening thread that is isolated from the main program code thread. The listening thread listens for incoming requests from clients. For each client it responds to, a new thread is created to serve the client. The corresponding events are then serviced in the context of that thread.

Practical examples
The following examples should help you get started with components for easy to use, but in order to demonstrate examples made as simple applications. Some projects are made to demonstrate different situations. These examples are also available for download as zip files.
Note from the translator: the link on the site is not working.
Example 1 - Postal code verification
The first project is made as simple as possible. Search by zip code, the client asks the server which city and state the specified zip code belongs to.
For those who live outside the US and don't know what a zip code is, it is a postal code that indicates the delivery location. Postal codes consist of 5 digits.
Protocol
The first step in building a server and client is developing a protocol. For standard protocols, this is defined by the corresponding RFC. For postal code, the protocol is defined below.
Most communication protocols operate in text mode. Exchange means that a command is transmitted, and in response, status and possibly data. The protocols are not limited to exchange, but plain text is still used. The protocol for determining the postal code is also text-based. Plain text makes protocols easy to debug and allows different programming languages ​​and operating systems to communicate.
After connecting, the server sends a hello message, then accepts the command. This command can be "ZipCode x" (Where x is the zip code) or "Quit". In response to the ZipCode command, a response is sent in the form of a single line with the answer or empty line if the code is not found. The Quit command causes the server to close the connection. The server may accept several commands before the Quit command is sent.
Server source code

unit ServerMain;

interface

uses

type

TformMain = class(TForm)

IdTCPServer1: TIdTCPServer;

procedure FormCreate(Sender: TObject ) ;

procedure FormDestroy(Sender: TObject ) ;

procedure IdTCPServer1Connect(AThread: TIdPeerThread) ;

private

ZipCodeList: TStrings;

public

end ;

FormMain: TformMain;

implementation

(R*.DFM)

procedure TformMain.IdTCPServer1Connect (AThread: TIdPeerThread) ;

begin

AThread.Connection .WriteLn ( "Indy Zip Code Server Ready." ) ;

end ;

SCommand: string ;

begin

SCommand:= ReadLn ;

end ;

end ;

end ;

procedure TformMain.FormCreate (Sender: TObject ) ;

begin

ZipCodeList:= TStringList.Create ;

ZipCodeList.LoadFromFile(ExtractFilePath(Application.EXEName) + "ZipCodes.dat");

end ;

procedure TformMain.FormDestroy (Sender: TObject ) ;

begin

ZipCodeList.Free ;

end ;

end.

The only Indy-specific parts in the project are the IdTCPServer1 component, the IdTCPServer1Connect and IdTCPServer1Execute methods.
The form contains the IdTCPServer1 component of type TIdTCPServer. The following properties have been changed: ·Active = True - After the application starts, the server listens. ·DefaultPort = 6000 - Port value for this project. The server listens for client requests on this port.
The IdTCPServer1Execute method is associated with the server's OnExecute event. The OnExecute event is raised after the client connection is accepted. The OnExecute event is different from other events you know. OnExecute runs in the context of a thread. The thread event is raised and given the AThread argument passed to the method. This is important because multiple OnExecute events can be executed at the same time. This is done so that the server can work without creating a new component. There are also methods that can be overridden when constructing heirs.
The OnConnect event is fired after the connection has been accepted and a thread has been created for it. IN this server this is used to send a welcome message to the client. If desired, this can also be done in the OnExecute event.
The OnExecute event can be fired multiple times until the connection is disconnected or lost. This eliminates the need to check the connection for disconnection or loss in a loop within an event.
IdTCPServer1Execute uses two basic functions, ReadLn and WriteLn. ReadLn reads a string from the connection, and WriteLn sends a string to the connection.
sCommand:= ReadLn;
The above code takes a string from the client and places it in the local sCommand string variable.

if SameText (sCommand, "QUIT" ) then begin

end else if SameText (Copy (sCommand, 1 , 8 ) , "ZipCode " ) then begin

WriteLn(ZipCodeList.Values[Copy(sCommand, 9, MaxInt)]);

end ;


Next, sCommand is checked for valid commands.
If the command is "Quit" then Disconnection is performed. No reading or writing is allowed after disconnection. After the event ends, the listening thread no longer calls it, but clears the thread and terminates the connection.
If the command is "ZipCode", then the parameter after the command is extracted and the table is scanned for the presence of the city and state. The city and state are then passed to the client, or an empty string is passed if there is no match.
Next, the method exits. The server will re-raise the event again as soon as a new command arrives, allowing the client to send multiple commands.
Client source code

unit ClientMain;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, ExtCtrls, IdAntiFreezeBase,

IdAntiFreeze, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient;

type

TformMain = class(TForm)

Client: TIdTCPClient;

IdAntiFreeze1: TIdAntiFreeze;

Panel1: TPanel;

Panel2: TPanel;

MemoInput: TMemo;

LboxResults: TListBox;

Panel3: TPanel;

Button1: TButton;

Button2: TButton;

Label1: TLabel;

procedure Button2Click(Sender: TObject ) ;

procedure Button1Click(Sender: TObject ) ;

private

public

end ;

FormMain: TformMain;

implementation

(R*.DFM)

procedure TformMain.Button2Click (Sender: TObject ) ;

begin

MemoInput.Clear ;

LboxResults.Clear ;

end ;

procedure TformMain.Button1Click (Sender: TObject ) ;

I: integer ;

S: string ;

begin

ButnLookup.Enabled := true ; try

LboxResults.Clear ;

with Client do begin

Connect; try

LboxResults.Items.Add(ReadLn);

for i:= 0 to memoInput.Lines .Count - 1 do begin

WriteLn("ZipCode" + memoInput.Lines[i]);

LboxResults.Items.Add(memoInput.Lines[i]);

S:= ReadLn ;

if s = "" then begin

S:= "-- No entry found for this zip code.";

end ;

LboxResults.Items.Add(s);

LboxResults.Items.Add("");

end ;

WriteLn("Quit");

finally Disconnect; end ;

end ;

finally butnLookup.Enabled := true ; end ;

end ;

end.


The only parts specific to the client component are the Button1Click method.
The Client component is of type TIdTCPClient and placed on the form. The following properties have been changed: ·Host = 127.0.0.1 - The server is located on the same machine as the client. ·Port = 6000 - Server port
The Button1Click method is associated with the OnClick event of the Button1 component. When the button is clicked, this method is called. The Indy part of this method can be reduced to the following: 1.Connect to the server (Connect;) 1.Read the greeting from the server. 1. For each line entered by the user in TMemo: 1. Sending a request to the server (WriteLn("ZipCode " + memoInput.Lines[i]);) 1. Reading a response from the server (s:= ReadLn;) 1. Sending the Quit command (WriteLn("Quit");) 1.Disconnect (Disconnect;)
Testing
This example has been tested and works with TCP/IP installed. You can change it to work over a network from one computer to another. By starting the server on another computer and changing the name or IP of the server on the client.
To test projects, compile and run the server. Then compile and run the client. Enter your postal code in the memo field and press the lookup key.
Debugging
Text protocols are very easy to debug because they can be tested using Telnet. To do this, it is enough to know the server port. Zip Code Lookup Server listens on port 6000.
Start Zip Code Lookup Server again. Then open a console (eg a Dos window). Now enter:
telnet 127.0.0.1 6000
You are now connected to the server. Some servers also send a welcome message. Some don't. You will not see the lines you enter. Most servers do not echo in order to save traffic. However, you can change the telnet settings by setting the "Echo On" option. This is done differently in different telnet clients, and some do not have this feature at all. Now enter:
zipcode 37642
You will see the server response:
CHURCH HILL, TN
To disconnect from the server, enter:
quit
Example 2 - database access
This example emulates a server that must perform blocking tasks other than socket calls. Many servers are forced to work in such conditions. Servers that need to access the database, calls external procedures or calculations often cannot interrupt these calls, because they are external calls or because of the complexity of this. Access to the database cannot be broken into small pieces and the developer must wait for the end of the operation with the database. This is a feature not only of database calls, but also of other operations such as compression, calculations and other processing of the same kind.
For demonstration purposes, let's imagine that the server makes a database call that takes 5 seconds to complete. To simplify, let's do this simply with a pause, use the Sleep(5000) function for this, instead of actually calling.
This example also requires less detail than the previous example because many of the concepts are not yet understood.
Source

unit main;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

IdBaseComponent, IdComponent, IdTCPServer;

type

TformMain = class(TForm)

IdTCPServer1: TIdTCPServer;

procedure IdTCPServer1Execute(AThread: TIdPeerThread) ;

private

public

end ;

FormMain: TformMain;

implementation

(R*.DFM)

procedure TformMain.IdTCPServer1Execute (AThread: TIdPeerThread) ;

I: integer ;

begin

with AThread.Connection do begin

WriteLn("Hello. DB Server ready.") ;

I:= StrToIntDef(ReadLn, 0);

// Sleep is substituted for a long DB or other call

Sleep(5000);

WriteLn(IntToStr(i * 7));

end ;

end ;

end.

Because the Execute event occurs in the context of a thread, the processing code can be of any length. Each client has its own thread and does not block other clients.
Testing
To test the DB server, compile and run it. Connect to it using Telnet to port 6001. The server will respond with a welcome message. Enter number. The server will “process” your request and respond within 5 seconds.

Indy components used in Delphi 6.

In addition to basic Internet services and protocols, there is a wide range of additional services, the capabilities of which are often used by Internet developers. In addition, the ability to display information using a browser is not always an acceptable solution for Internet applications. In this case, it is reasonable to use the Internet infrastructure for data exchange, and provide information display through more complex client applications developed, for example, in Delphi.

Let's say you need to implement specialized server logic that is not included in standard Web servers. To solve this class of problems, Delphi includes the Internet Direct (Indy) library from Nevrona Designs (http://www.nevrona.com/Indy/). This library, developed specifically for Borland Delphi, already has eight versions, the latest of which is included in the new version of Delphi. The set of components is divided into three groups: client (Indy Client), server (Indy Servers) and auxiliary (Indy Misc).

Indy Clients and Indy Servers

Most Indy Client and Indy Servers components are pairs corresponding to the client and server parts of the protocols and services (with the exception of certain, mainly server, components such as TunnelMaster and TunnelSlave), and allow the use of protocols such as TCP/IP, UDP, NNTP, SMTP, FTP, HTTP, as well as services ECHO, FINGER, WHOIS, etc.

Indy client components are written using sockets. The client side socket requires a connection to the server. If the connection is established, the client and server can begin exchanging messages. These messages are of a different nature, but usually the exchange occurs using a specific protocol (for example, HTTP)

TIdTCPClient and TIdTCPServer

These components are used to support one of the main network protocols - TCP (Transmission Control Protocol), and are also the base classes for the TIdSMTP and TIdFTP components. The TIdTCPServer class has a ThreadMgr property that defaults to nil. If ThreadMgr is nil when TIdTCPServer is enabled, the TIdThreadMgrDeafault class will be created implicitly. Otherwise, the installed process manager is used.

TIdUDPClient and TIdUDPServer

These components are used to support the UDP (User Datagram Protocol) network protocol and are also the base classes for a number of other Indy components.

TIdChargenServer

The component is used to generate random symbols, usually for testing purposes.

TIdDayTime and TIdDayTimeServer

The components are used to provide time service. The client requests, and the server reports the current date and time.

TIdDNSResolver

This is a client component that serves requests from a DNS (Domain Name Service) server. DNS server queries are designed to replace a computer's name with its IP address. TIdDNSResolver is a descendant of the TIdUDPClient class.

TIdDICTServer

A server component that supports the Dictionary Server Protocol (DICT), a server-side dictionary based on the TCP protocol that allows a client to access a natural language dictionary.

TIdDISCARDServer

The server component that supports the records server. The recordings can be used as a debugging and measurement tool. The records service simply hands over any data to whoever is willing to receive it.

TI dEcho and TI dECHOServer

The components are designed to provide a response service, typically used to check the health of the network. The client sends a text message to the server, the server returns the message to the client. If the message is garbled, the network malfunctions.

TIdFinger and TIdFingerServer

The components are designed to provide a protocol that allows a user to query data regarding the presence of other users on the system. Some servers handle such client requests. Using this pair of components will allow you to service client requests that determine the presence of other users on the system.

TIdFTP

The component includes full support for the file transfer protocol - FTP (File Transfer Protocol). Passive and active data transfer is supported, as well as operations such as GET and PUT, deleting directories, obtaining quotas, file and directory sizes. TI dFTP uses the TIdSimpleServer class to operate. When an FTP file transfer is in progress, a secondary TCP connection is opened for data transfer and is closed when the data has been transferred. This connection is called a “data link,” which is unique for each file being transferred.

TIdGopher and TIdGopherServer

These components are designed to provide a network protocol that has recently been supplanted from the WWW (World Wide Web) by the HTTP protocol. The server that implements this protocol provides a hierarchical distributed document flow support system. An example of using this pair of components, located in the \demos\indy\GopherClient and \demos\indy\GopherServer directories, demonstrates how using this protocol you can provide information about files on your computer, including closed ones, on the local network .

TIdHostNameServer

A server component designed to pass the local server name to clients.

TIdHTTP and TIdHTTPServer

The components are used to provide the HTTP network protocol (versions 1.0 and 1.1 are supported, including GET, POST and HEAD operations). In addition, support is provided for authentication and the use of proxy servers. The server component is used to provide services to another Web server that supports a given protocol. TIdHTTPServer facilitates the implementation of functions such as cookies, state management, etc.

TIdIcmpClient

A client component designed to provide the Internet Control Message Protocol (ICMP), which is used to perform ping operations and network tracing.

TIdPOP3

A client component designed to provide the Post Office Protocol (POP), including support for MIME encoding and decoding, and multibyte character transmission.

TIdIMAP4Server

A server component designed to support IMAP (Internet Message Access Protocol) operations on the server. The protocol allows you to search for email messages on the server. The difference between the IMAP and POP protocols is that the POP protocol requires additional memory to store data, and the IMAP protocol accesses the server instead of the client machine. IMAP4 was created to replace POP3, but POP3 remains a widely used standard to this day.

TIdIRCServer

A server component designed to support the most commonly used service operations on the Internet, commonly called chat. The component provides the basic building blocks for an IRC (Internet Relay Chat) server.

TIdMappedPortTCP

A server component designed to create mapped ports, which are often used in proxy servers. The methods of this component allow you to map one port to another. For example, port 80 could be mapped to port 3000, and all requests to the first port (port 80) would be forwarded to the second port (port 3000).

TIdNNTP and TIdNNTPServer

These components are required to support the Network News Transfer Protocol (NNTP) used in news services. The client component includes support for MIME encoding and decoding, as well as support for multibyte characters and alternate encodings. The server component allows you to create news servers. It is important to note that TIdNNTPServer is not a full-featured news server, but a component that provides the basic functionality for such a server.

TIdQOTD and TIdQOTDServer

The components are used to provide the Quote of the Day service. The client component connects to the server component instance to obtain the daily quote. Each server instance contains a unique citation database.

TIdSMTP

A client component designed for use in Simple Mail Transfer Protocol (SMTP) applications, providing support for authentication, MIME encoding and decoding, and multi-byte character support.

TIdSNTP

A client component designed to provide SNTP (Simple Network Time Protocol) - a time service. Can be used to connect to any time service to determine the current date and time.

TIdSimpleServer

Server component that provides a lightweight TCP server. Allows you to organize a point-to-point connection. It is used to create servers with a single user, that is, it can only serve one connection at a time. Unlike the TIdTCPServer component, it does not spawn secondary processes when waiting for requests from clients and when processing these requests. In other words, if the server is serving a request from a client, and at that time another client is contacting it to connect, then it will be blocked until the end of processing the first request.

TIdTelnet and TIdTelnetServer

The client component is used to organize remote sessions on another computer, including console negotiations and authentication. The communication protocol assumes the presence of a person interacting interactively with the server. The client component does not have display support or terminal emulation, but simply provides a connection to the server part. Typically, the TIdTelnetServer server protocol is used to organize remote databases with a text interface for interactive interaction with clients.

TIdTime and TIdTimeServer

The client component is an alternative to the TIdSNTP component for determining time. It is important to note that the formats of the two protocols are different. TIdTime is based on the RFC 868 format (returns the time in the internal UNIX OS standard, performing all necessary conversions). The server component is similar in functioning to the DayTime server. Can be used to implement a time service on the local computer. No additional code is required, just create an instance of TIdTimeServer that will return the time of the server computer's internal clock.

TIdTrivialFTP and TIdTrivialFTPServer

These components are necessary to organize a simple file transfer protocol. The client component of this protocol is used to connect to an instance of the corresponding server component. The protocol is intended for private, lightweight, local cases of file transfer, for example in local area networks or for loading (uploading) routing tables into routers. Due to the weakened characteristics of this protocol, its use is not recommended when using authentication algorithms or any other security mechanisms. The main purpose of this protocol is to transfer files to a hardware device for the purpose of modifying it.

TIdTunnelMaster and TIdTunnelSlave

Server tunnel components are used in proxy servers to organize multiple logical connections over one physical (tunnel). These classes can be used for various purposes, for example, to organize a secret connection over non-secret channels.

TIdWhois and TIdWhoIsServer

This client component connects to any standard Whois server, allowing you to obtain information about domains. The server component provides the basic functionality of a NIC server.

Indy Misc

The Indy Miscellaneous Components page includes BASE64, UUE, Quoted Printable and other common email communication formats, encoders (MD2, MD4 and MD5) for cryptography standards used to store passwords and electronic signatures in an irreversible (hard to decrypt) form, as well as many other useful components and utilities often used in the development of Internet applications.

TIdAntiFreeze

Due to the block-based algorithms of Indy components, it often appears that the application is stuck while the connection is working. To eliminate the use of secondary processes (threads) when organizing communications to prevent the application from freezing, it is enough to place the specified component on the form.

The component works by parsing requests from the TCP/IP protocol stack and sending messages to the application during the delay when external connections are blocked, which creates the illusion of running code. Since the component affects blocked connections only for the main process, the use of TIdAntiFreeze in secondary processes of the application is not required. Be aware that the TIdAntiFreeze component slows down connections because the main process is periodically interrupted to process messages. It follows that care must be taken to ensure that the application being developed does not spend too much time processing messages, including OnClick, OnPaint, OnResize, etc. To some extent, this can be controlled through the properties of the TIdAntiFreeze class. The use of this component is not mandatory, but it allows you to solve the problem of synchronizing connections with the visual interface of the application.

TIdDateTimeStamp

A class for performing date and time math related to the fact that Internet protocols use different date and time formats; in addition, clients and servers may be located in different time zones.

TIdIPWatch

It is a timer-based component that constantly monitors changes in the computer's IP address. Component events occur when a change is detected. This component is usually used to detect whether a computer is connected to the Internet or any other network. The change in IP address in this situation may occur due to the IP address being assigned by the DHCP (Dynamic Host Configuration Protocol) server when connecting to the new network.

TIdLogDebug

The purpose of this component is to intercept events of any client or server component and place a record of the event in the specified file. This component is very useful for debugging Indy components.

TIdMessage

The component is used in combination with other components to properly decrypt or encode messages. These can be POP, SMTP and NNTP components. The class supports MIME encryption and decryption, multibyte characters, and ISO encoding.

TIdNetworkCalculator

One of the few Indy components that can be used when building applications. The network calculator can be used to perform calculations on IP addresses, including network masks, subnet, network classes, etc.

TIdThreadMgrDefault

The component provides control of secondary processes by default. Created when any Indy component that supports process management does not have an instance of the TIdThreadManager class defined. The component provides only basic capabilities for managing secondary processes: creating and destroying them on demand.

TIdThreadMgrPool

A more advanced process management component than TIdThreadMgrDefault because it merges processes rather than creating or destroying them on demand.

TIdVCard

VCard is the electronic equivalent of a business card and may contain the owner’s personal information and graphic data.

TIdIMFDecoder

Designed for decoding Internet messages. It is a descendant of the TIdCoder class, just like all other encoder components. The TIdCoder class decodes according to the ARPA Internet text message format standard RFS-822, proposed in August 1982, and the USENET messaging standard RFC 1036, proposed in December 1987.

The component extends the TIdCoder class to allow detection of RFS-822 format by header context, providing decrypt-on-receive mode and MIME encryption and decryption. The TIdIMFDecoder component is used in the TIdMessageClient class to decode received and transmitted messages.

TIdQuotedPrintableEncoder

QuotedPrintableEncoder allows you to decrypt text in the specified format. Can serve as a standalone component with a specified encoding type, allowing messages containing a new encoding type to be transmitted.

TIdBase64Encoder

Implements another encryption algorithm that makes it possible to transmit non-printable characters.

TIdUUEncoder

Implements one of the first encryption algorithms, UU encoding. Sometimes used when mailing articles to a news service.

TIdXXEncoder

This encryption method is unlikely to ever be used. Essentially, this is the same UU encoding, but with a different encryption table.

TIdCoderMD2

Components with different types of MD (Message Digest) encryption algorithm. They are all shuffle-based, one-way, and have no decryption algorithms.

Components of protocol clients and servers can be used to develop server and client Internet applications, together with or instead of basic ones (ClientSocket, ServerSocket) and other components from the Internet and Fastnet palette. Indy components do not use the WebBroker architecture, implementing low-level support for Internet protocols and services directly in their source code (source codes included).

TIdConnectionInterceptOpenSSL and TIdServerInterceptOpenSSL

The SSL protocol - Secure Sockets Layer, which ensures the secrecy and reliability of communication between two applications, has two layers. At the low level of a multi-layer transport protocol (such as TCP), SSL is a recording protocol and is used to encapsulate various higher-level protocols. The advantage of SSL is that it is an independent application protocol, but a higher-level protocol can be used on top of SSL.

SSL provides communication security, which has three main functions: providing a confidential connection; public key encryption (used to confirm the identity of the recipient); support for data transmission reliability.

  • Symmetric cryptography is used to encrypt data (eg DES, RC4, etc.).
  • The digital signature is provided using asymmetric public key encryption (for example, RSA, DSS, etc.).
  • Reliability of communication, message transport includes checking the integrity of the message through MAC correction codes, secure hash functions (eg, SHA, MD5, etc.) using MAC calculations.

In combination with HTTP and server authentication, SSL provides the necessary encryption functions and further maintains the established connection by cross-checking the identity of the Web server, etc. It is important to understand that SSL only protects communications during data transfer and does not replace other security mechanisms.

The TIdConnectionInterceptOpenSSL and TIdServerInterceptOpenSSL components provide both client-side and server-side connections using the SSL protocol. It should be noted that the TIdConnectionInterceptOpenSSL and TIdServerInterceptOpenSSL components are only available in Delphi 6, and not in Kylix. This is due to the complexity of the protocol, which in the case of a Windows implementation is based on operating system functions.

Examples of using Indy components can be found in the /Delphi6/Demos/Indy directories. In total, the Indy library in version 8.0 contains 69 components. It is stated that in version 9.0 the specified library will contain 86 components. All components are unified and included in both Delphi 6 and Kylix, which allows them to be used for developing cross-platform applications. All Indy components support multithreading.

The Indy components implement almost all the functionality found in the Internet and Fastnet components, as is clearly shown in the table.

Fastn et components Indy components Purpose of components
1 TserverSocket, TClientSocket TIdTCPserverSocket, TIdTCPClientSocket Interaction between two computers (client and server) using the TCP/IP protocol
2 TNMDayTime TIdDayTime, TIdDayTimeServer Query the server for the current time
3 TNMEcho TIdEcho, TIdEchoServer Used to communicate with the response server
4 TNMFinger TIdFinger, TIdFingerServer Used to obtain information about the user from an Internet search server
5 TNMFTP TIdFTP, TIdTrivialFTP, TIdTrivialFTPServer Provide file transfer using FTP protocol
6 TNMHTTP TIdHTTP, TIdHTTPServer Use HTTP protocol for data exchange
7 TNMMsgServ, TNMMsg Used to transmit simple text messages from client to server
8 TNMNNTP TIdNNTP, TIdNNTPServer Supports data exchange with news server
9 TNMPOP3 TIdPOP3 Used to receive email from a mail server using the POP3 protocol
10 TNMSMTP TIdSMTP Used to send email via Internet mail server
11 TNMStrm, TNMStrmServ Transmits binary data written to a stream using the TCP/IP protocol
12 TNMUDP TIdUDP, TIdUDPServer Transfer data using the UDP protocol
13 TpowerSock, TNMGeneralServer Component-encapsulated classes that are the basis for writing your own clients (Powersock) and servers (NMGeneralServer)
14 TNMUUProcessor TIdUUEncoder, TIdUUDecoder Converts binary files to MIME or UUENCODE format
15 TNMURL Converts strings to HTML format and performs reverse conversion

The exceptions are classes such as TNMMsgServ, TNMMsg, TNMStrm, TNMStrmServ, TpowerSock, TNMGeneralServer, TNMURL, which either implement obsolete protocols or have functionality implemented in a large group of alternative classes.

However, unlike its predecessors - the Internet and Fastnet components, Indy contains richer server components and components for data transcoding and encryption, as well as authentication support (Indy Misc palette). As can be seen from the table above, the main protocols and services are provided not only by client, but also by server components. These are time services, response services, obtaining user information, as well as HTTP, NNTP, UDP protocols and even the simplest version of FTP.

Some examples of using Indy components

In Indy components contained in Delphi, the IP address is defined in the Host property, typically only in client applications. Server-hosted components have methods that allow you to start or stop polling the corresponding port - for example, changing the Active property of the IdTCPServer component starts or stops polling the corresponding port. Once the connection between the client and server is established, data transfer can begin.

Indy components place great emphasis on security and reliability when working with data. For example, the IdTCPClient component has Connect and Disconnect methods. Using a programming technique like the below code from the client side:

with TCPClient do begin Connect; try lstMain.Items.Add(ReadLn); finally Disconnect; end; end;

and using the Connection property passed as a parameter to the AThread instance of the TIdPeerThread class from the server side:

with AThread.Connection do begin WriteLn("Hello from Basic Indy Server server."); Disconnect; end;

you can count on either the normal execution of the connection or the correct error handling.

Note the ReadLn and WriteLn methods of the corresponding classes - they resemble standard Pascal I/O statements. This is a tribute to the UNIX programming technique, where most system operations are performed by reading and writing to the corresponding files.

Just like Fastnet components, Indy component classes have events that can be used to provide event management. For example, you can arrange for a message to be displayed on a form when connecting to a client:

procedure TForm1.IdECHOServer1Connect(AThread: TIdPeerThread); begin lblStatus.caption:= "[ Serving client ]"; end;

Indy provides components that implement protocols with client and server parts that are unique to this library. The TIdGopherServer and TIdGopher components, thanks to the GetExtendedMenu, GetFile, GetMenu, GetTextFile methods on the client side and ReturnGopherItem, SendDirectoryEntry on the server side, help to view files of various types, including those marked as hidden, as well as directories on a remote computer (similar to as the dir *.* command does in the MS-DOS operating system).

Using the IdSMTP and IdMessage components, you can easily create your own Web application that can send mail using the SMTP protocol.

In this case, the IdMessage class (one of 23 components from the Indy Misc page) is responsible for generating the message, which follows from its name, and IdSMTP is for organizing the connection with the mail server.

The technology used in Indy uses locking read and write operations. Any Connect operation used in Indy waits for the connection to complete. When working with Indy client components, you typically need to do the following:

  • request a connection to the server;
  • make read and write requests to the server (depending on the type of server, the step is performed once or repeated many times);
  • end the connection to the server and disconnect.

Indy components are designed to provide an ultra-high level of abstraction. The intricacies and details of the TCP/IP stack are hidden from the programmer so that he can focus on the task at hand.

The following small example shows a typical client bean session:

with IndyClient do begin Host:= "zip.pbe.com"; // Host to call Port:= 6000; // Port to call the server on Connect; try // Your code goes here finally Disconnect; end; end;

In the example, even if the connection to the server is not established, the connection will be gracefully terminated due to the use of the try-finally statement.

Indy's server components describe a variety of server models that can be used depending on your needs and the protocol you're using.

TIdTCPServer is the most commonly used server component, which creates a secondary process independent of the main application process. The created process awaits incoming requests from potential clients. An individual secondary process is created for each client whose request it responds to. Events that occur during the maintenance process are related to the context of the corresponding processes.

In other words, for each client connection, the TIdTCPServer class uses a unique secondary thread by calling that thread's OnExecute event handler. The formal parameter of the OnExecute method is a reference to an instance of the Athread class corresponding to the created thread. The Connection property of this class is a reference to the TIdTCPConnection class, an instance of which is created to process the client request. TIdTCPConnection supports reading and writing over the connection, as well as establishing and terminating a communication session.

The UDP protocol works without first establishing a connection with the server (each sent packet is an independent set of data, and not part of a larger session or connection). While TIdTCPServer spawns separate threads for each connection, TIdUDPServer uses either a main thread or a single secondary thread that handles all UDP protocol requests. When TIdUDPServer is active, a thread is created to listen for incoming UDP packets. For each packet received, an OnUDPRead event is raised either on the main thread or in the context of the listening thread, depending on the value of the ThreadedEvent property. When ThreadedEvent evaluates to False, the event occurs on the main thread, otherwise it occurs on the listening thread. While the event is being processed, other server operations are blocked. Therefore, it is important to ensure that OnUDPRead procedures run as quickly as possible.

If you need to create a new client application for an existing server using an existing protocol, your job is solely to develop and debug the client application. However, when we have to develop both client and server applications using an existing or new protocol, we are faced with the classic “chicken and egg” problem. Where to start programming - from the client or from the server?

Obviously, both the client and the server must be created eventually. For many applications, especially those using a text-based protocol (such as HTTP), it is easier to start building the application by designing the server. And for debugging there is a convenient client that already exists. This is a Telnet console application that is available on both Windows and UNIX.

If you type the console command telnet 127.0.0.1 80 with the IP address of the local computer and port number 80, which is used by default by Web servers, the application will respond with the text shown in Fig. 6, in case of Windows 2000 OS and IIS 5.0.

To create the simplest server using Indy components you need:

If you need to design a server that will not only correctly inform its clients when the connection is lost, but also provide them with information about error situations that have occurred, use the try-except statement instead of try-finally - for example, as shown in the following example:

procedure TDataModule1.IdTCPServer1Execute(AThread: IdPeerThread); var s: String; begin with AThread.Connection do try try s:= ReadLn; // Perform the task of the server here // if no exception is raised, // write out the server's response WriteLn(s); except on e: Exception do begin WriteLn(e.Message); end; //on end; //try except finally Disconnect; end; end;

This small example demonstrates the steps to create a simple text server, as well as how to debug it.

The server described above is a typical example of the organization of modern distributed computing.

Features of creating multi-tier applications

Recently, multiple servers are increasingly being used to satisfy client requests. A server of this type, having received a client request and partially prepared it for further processing, contacts another server and sends it the transformed request or requests. The second-tier server can, in turn, communicate with other servers. Thus, we can talk about a multi-tier server architecture.

Next we will create a data access server whose purpose is to return data from the database. This server, however, does not read or write to the database files directly. Instead, it communicates with the database server in search of the data required by the client.

So, we start developing an application with a three-tier architecture. To create a database server using Indy components you need:

  1. Create a new project.
  2. Place an instance of the TIdTCPServer component from the Indy Servers palette on the main form of the project.
  3. Set the DefaultPort property of the TIdTCPServer1 class instance to 6001 (it is recommended to assign large values ​​to avoid duplicating port numbers across different applications), and set the Active property to true.
  4. Add a new module to the project by selecting the File | New | Data Module, and place instances of the SQLConnection and SQLDataSet components on it from the dbExpress tab on the components palette.
  5. Set the ConnectionName property of the SQLConnection class to IBLocal and LoginPrompt to False. If you have not configured IBLocal on the employee.gdb database, complete this procedure first.
  6. Set the SQLConnection property of the SQLDataSet class to SQLConnection1 and assign the CommandText property to the SQL statement: select CUSTOMER, CONTACT_FIRST, CONTACT_LAST from CUSTOMER where CUST_NO = :cust.

Hi all!

When developing the next Web project, the task arose - to implement client software in Delphi, which would transfer data to the server using the POST method. The application must transmit text and upload files to the Web server.

Implementation of such data sending using server-side languages Web development(for example, PHP) is quite simple, but if you need to write application-based, multi-user software that interacts with the server, then it’s a little more complicated. The method of directly connecting to the database and via FTP to the server from Delphi is no longer necessary because it is not safe, not reliable (changing passwords, connection data, etc.) and creates additional. software compatibility problems on the client side. To solve the problem, I decided to write scripts (server part) in PHP that will process incoming POST requests and return the result to the client (Delphi application). The advantages of this approach are that all connections and data processing occur on the server, which is much safer than a direct “connection”.

When I started googling, a lot of scattered information was given up, mostly on forums, but it was all in pieces. One thing was certain that Indy would be used, namely the IdHTTP component with the POST method implemented. In fact, everything is simple, this method takes two parameters Url of a resource and DataStream (data stream), and returns the result in text form (it can also be the HTML code of the page). The main thing was the correct formation of the DataStream (stream of transmitted data), but along the way additional pitfalls emerged, namely the Russian encoding (if it were not good). This is where the fun began for several hours of wandering around the Internet. In general, enough chatter, let's move on to practice and implementation of the software.

So the program is simple. She must send data to the server using the POST method, the data contains " Heading " (line), " Description » ( multiline text) And graphic file(jpg,png,gif-binary data). The server must accept this data, process it, save the graphic file on the server and return a response. As a response, we will return Delphi to the application, the same text only with added labels and a link to the downloaded file. Nothing else.

Let's start with the implementation of the server part (similar to the site's API). Open any text editor(notepad) and write the following code in it:

"; ) else ( echo "Title: Missing"."
"; ) //Check the incoming data for the presence of the "content" field data if (!empty($_POST["content"]))( echo "Content: ".$_POST["content"]."
"; ) else ( echo "Content: Missing"."
"; ) //Check the incoming data for the presence of an attached file "file" if (!empty($_FILES["file"])) ( $finfo = pathinfo($_FILES["file"]["name"]); / /get information about the file (name, extension, etc.) //Check the file type in the list of allowed types (IMPROVISATION:)) if (stripos("jpgpnggif",$finfo["extension"])==0)( echo ">>>>>>>Invalid file type<<<<<<<<"; exit; //Если не допустим тип, полностью останавливаем скрипт } $fname = "files/" . "testimgfile." . $finfo["extension"]; //формируем путь и новое имя файла move_uploaded_file($_FILES["file"]["tmp_name"],$fname);//сохраняем временный файл "tmp_name" в файл $fname echo "http://".$_SERVER["HTTP_HOST"]."/".$fname; //возвращаем полный путь к файлу } ?>

note! When saving (via notepad), you must specify the encoding “UTF-8”, otherwise there will be problems with displaying the Cyrillic alphabet!

The script tried to provide detailed comments. Copy this script to your Web server, if you don’t have one, you can use my script for the test, it is located at: http://api..php

The layout uses the following components: Label, Button (2 pcs.), Edit (2 pcs.), Memo (2 pcs.), CheckBox, OpenDialog, IdHTTP. Give the following components names (property “ Name”):

  1. Edit(title) – Name=title;
  2. Edit(path to file) Name = imgfile;
  3. Memo(Contents)Name = content;
  4. Memo(Result) – Name = response;
  5. Button(…) – Name = chkfile;
  6. Button(POST) – Name = PostBut;
  7. OpenDialog (File selection dialog) – Name = PictDialog;

Let's leave IdHTTP1 and CheckBox1 unchanged (tired! :)))).

So as not to accidentally " edit» path to Edit( imgfile), set its ReadOnly property to True. Likewise, at imgfile And chkfile Set the Enabled property to false. We will activate them using CheckBox, i.e. We will provide the opportunity to choose whether to upload an image or not.

For OpenDialog( PictDialog) you need to set the filter (Filter property) as follows:

The actual visual preparation is over! Let's start coding!

In the project we will generate a data flow using the type included with Indy - TidMultiPartFormDataStream. Although we came across implementation options using TStream, working with TidMultiPartFormDataStream – easier!

To make this type available to our project, we need to add the following library to Uses: IdMultipartFormData.

For CheckBox1, create an OnClick event (by double-clicking the mouse on an object) and add the following code to this event:

Procedure TForm1.CheckBox1Click(Sender: TObject); begin //make active or inactive the file path elements and dialog buttons imgfile.Enabled:=CheckBox1.Checked; chkfile.Enabled:=CheckBox1.Checked; end;

Here we activate the objects imgfile Andchkfile depending on the presence of a checkmark (if the checkbox is checked, then the objects become active).

Now let's organize the image selection. To do this, create an OnClick event on the button chkfile(also by double clicking on the object) and write the following:

Procedure TForm1.chkfileClick(Sender: TObject); begin //open the dialog and enter the full path to the file in imgfile(TEdit) if PictDialog.Execute then imgfile.Text:= PictDialog.FileName; end;

This event will trigger an image selection dialog and if the user clicks " Open", then the path to this file will be added to imgfile.

And now we come to the final “POST” button. Create an OnClick event for this button and add the following code:

Procedure TForm1.PostButClick(Sender: TObject); var dataPost:TIdMultiPartFormDataStream; begin dataPost:=TIdMultiPartFormDataStream.Create; dataPost.AddFormField("title",title.Text,"utf-8").ContentTransfer:= "8bit"; dataPost.AddFormField("content",content.Text,"utf-8").ContentTransfer:= "8bit"; if CheckBox1.Checked and (trim(imgfile.Text)="") then //checking whether the file is selected or not begin ShowMessage("You must select a graphic file!"); exit; end; if CheckBox1.Checked then dataPost.AddFile("file",imgfile.Text,""); //add a field with the file response.Text:= StringReplace(idHTTP1.Post("http://api..php",dataPost),"
",#13#10,); datapost.Free; end;

So, in order (although there are comments):

Datapost – object of type TIdMultiPartFormDataStream. Allows you to create a POST request structure consisting of fields of different types.

dataPost . AddFormField (" title ", title . Text ," utf -8 "). ContentTransfer := " 8 bit "; – adds a field named “title” to the DataPost, a value from “title.Text”, sets the encoding of the transmitted data to “utf-8” (the parameter is optional, but without its explicit indication, Cyrillic is transmitted with question marks “?”) and a very important method "Content Transfer". Without this method, data is sent to the server " abracadabra" Please note that the field name (“title”) on the sending side must match the name specified in the script: $_POST["title"].

Data is transferred similarly to the “content” field.

dataPost . AddFile (" file ", imgfile . Text ,"") – with this line we create a stream with data from the file.

That's it, the data is generated, all that remains is to transfer it to the script on the server and receive a response:

response.Text:= StringReplace(idHTTP1.Post("http://api..php",dataPost),"
",#13#10,);

because TMemo does not understand the line break tag "
", we will use the " " function to replace it with understandable line breaks "#13#10".

When everything is complete, clear the memory from the DataPost object with the line:

datapost.Free;

Although in our example this will happen automatically at the end of the procedure, but still...

The actual result of the program on the screen:

Thus, we can send as much data or files to the server as we want, process this data on the server and report back to the application the result of the script. It could even be just 0 or 1, which will signal the application to react further.

All. Good luck to all. I hope the information was useful and you will find use for it.

You can download the finished example and script.

Full module code:

Unit PostUnit; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdMultipartFormData, Vcl.ExtDlgs; type TForm1 = class(TForm) IdHTTP1: TIdHTTP; title: TEdit; content: TMemo; PostBut: TButton; response: TMemo; Label1: TLabel; Label2: TLabel; Label3: TLabel; imgfile:TEdit; chkfile: TButton; Label4: TLabel; CheckBox1: TCheckBox; PictDialog:TOpenDialog; procedure PostButClick(Sender: TObject); procedure chkfileClick(Sender: TObject); procedure CheckBox1Click(Sender: TObject); private ( Private declarations ) public ( Public declarations ) end; var Form1: TForm1; implementation ($R *.dfm) procedure TForm1.CheckBox1Click(Sender: TObject); begin //make active or inactive the file path elements and dialog buttons imgfile.Enabled:=CheckBox1.Checked; chkfile.Enabled:=CheckBox1.Checked; end; procedure TForm1.chkfileClick(Sender: TObject); begin //open the dialog and enter the full path to the file in imgfile(TEdit) if PictDialog.Execute then imgfile.Text:= PictDialog.FileName; end; procedure TForm1.PostButClick(Sender: TObject); var dataPost:TIdMultiPartFormDataStream; begin dataPost:=TIdMultiPartFormDataStream.Create; dataPost.AddFormField("title",title.Text,"utf-8").ContentTransfer:= "8bit"; dataPost.AddFormField("content",content.Text,"utf-8").ContentTransfer:= "8bit"; if CheckBox1.Checked and (trim(imgfile.Text)="") then //checking whether the file is selected or not begin ShowMessage("You must select a graphic file!"); exit; end; if CheckBox1.Checked then dataPost.AddFile("file",imgfile.Text,""); //add a field with the file response.Text:= StringReplace(idHTTP1.Post("http://api..php",dataPost),"
",#13#10,); datapost.Free; end; end.

Serge Dosyukov Mike Pham

This article shows you how to create a standalone Web service using the Indy kit and Delphi 7, and how to use the Indy kit to support Delphi 7 SOAP-based Web services. For more information on creating Web services, see Nick Hodges' excellent article on the Borland community site: Shakespeare on the Web.

Sooner or later, you may need to create a server that is a standalone HTTP server and supports Web services. For example, you might want to create a SOAP-based application server for an n-tier application built using Delphi.

Introduction

Delphi's online help provides excellent, step-by-step instructions on how to create a Web service, a MIDAS server (COM, DCOM), but there is virtually no information on creating a standalone n-tier SOAP-based MIDAS application.

Previously published by Dave Nottage. This article described the idea of ​​​​how to create a Web service in Delphi 6 with SOAP support and the ability to publish SOAP interfaces of the Datamodule, that is, this article allowed you to learn how to create your own n-tier MIDAS systems.

Borland's Delphi 7 and the new Indy kit have built-in support for this functionality.

However, despite built-in support, this feature is not documented.

Recent postings on the Borland networking conference and searching the web using a Google server have allowed the authors to develop a way to convert existing code from Delphi 6 to Delphi 7. But everything has its time.

main idea

This article is the first part of a three-part series. It describes the main provisions. The second and third parts will be devoted to some problems and ways to solve them. Let's start describing the main idea.

  • be a standalone HTTP server;
  • use Indy as a platform;
  • support publishing via SOAP protocol;
  • be capable of publishing SOAP DataModules, which would allow you to create your own n-tier server based on SOAP/HTML.

HTTP server and SOAP

Many people know Indy and have used THTTPServer components before. It's easy to put this component on an application form, but how do you make it support SOAP? In the directory "C:Program FilesBorlandDelphi7SourceIndy" you can find the file IdHTTPWebBrokerBridge.pas. This is exactly what you need.

This file is not part of the Indy executable, so you need to include it in your current project as a standard project file. (To compile the project, you will also need the IdCompilerDefines.inc file.) These files must be copied to the current project directory. Code changes may be required to increase speed, so it is best to keep these files separate from the Indy distribution.

The following describes the implementation of a replacement component from THTTPServer, extended to support SOAP packets, called TIdHTTPWebBrokerBridge. This construct is a class that inherits from TCustomHTTPServer and supports basic request binding.

Because this class is not accessible from the palette, you will need to define it as a regular object when executing your code.

This object can be used in exactly the same way as a regular THTTPServer, with the exception of those additional properties that enable operation with SOAP.
However, first let's look at preparing the necessary code.

WebBroker and Indy

For those who have created Web services before, you know that you use WebBroker. Delphi 7, like Delphi 6, uses the WebBroker architecture to support SOAP.

Therefore you need to create a module TWebModule and place the following three components in it: THTTPSoapDispatcher, THTTPSoapPascalInvoker and TWSDLHTMLPublish. All of them are available from the WebServices tab of the component palette. After linking SOAPDispatcher with SOAPPascalInvoker, the application form is ready. The end result should be something like what is shown in the following figure:

(module uWebModule.pas)

It's best to leave everything as is, since there is no need to change or execute any custom code for this form.

WebModule and Indy

Let's move on to the other part of the code needed to implement the HTTP server.

As you can see, TIdHTTPWebBrokerBridge has a RegisterWebModuleClass method, which allows you to register your own WebModule and make it available to the server.

Thus, after creating the fServer server object, you just need to call the fServer.RegisterWebModuleClass (TwmSOAPIndy) class.

Note. In a normal implementation of TIdHTTPWebBrokerBridge, a TwmSOAPIndy object will be created each time a request is received. Obviously this is not necessary. Therefore, the class can be modified to ensure the permanent creation of this object as long as the Server object exists. It is recommended that you refer to the class implementation documentation for more information.

Is the server ready?