[Sockets] Indy or ICS?

Posted on 2003-10-28
Last Modified: 2012-05-04
I don't want to start a flame-war but I often hear people praising the ICS components here while I myself just prefer the Indy components. So, a challenge. Define in up to 2000 words why we should use package [X] instead of package [Y] when developing client/server components through sockets. Why is it better? How is the performance? Or don't you have any preference?

Or vote on the person with the best arguments. I'll close this question in about two months again, awarding points to the person(s) with the most convincing arguments and/or the most votes.

I think it's just personal preference for most people but I wonder if someone has any good arguments to stick to his personal choice...
Question by:Wim ten Brink
  • 3
  • 2
  • 2
  • +1

Expert Comment

ID: 9637205
Well, you know what I prefer ;-) so I don't think there's any point in me continuing further!

Geoff M.

Accepted Solution

swift99 earned 250 total points
ID: 9638909
both tools have been used in small, medium, and large installations quite successfully.

I have not had any success with Indy, even with simple demo programs.  Since I am a long time ICS user, I did not have the motivation to pursue Indy very far when it became obvious that I would have to change strategies.

In contrast, I had my first ICS based FTP server up and running within five minutes of completing the installation.  it was a long ways from being production ready, but I had a working demo of my own creation.

There was a large learning curve that followed because ICS is a fully event driven state engine model, and it does not even try to look like a synchronous component.  However, once I grasped the non-blocking asynchronous nature of the tool, it became very easy to work with.

Many people have difficulty with moving to ICS because it is non-blocking and asynchronous.  You kick off a task (say a FTP get), but nothing happens until you give the OS control (say by doing a file I/O, or returning to the application's main event loop.  At that time, the state engine of the wrappered protocol is driven entirely by the Windows event loop.  

For example ...
    ICS_FTP1.GetAsync;  // non-blocking call

does not actually performe the GetAsync action.  it only sets up the condition where the getAsync will occur _IN ITS OWN TIME_.  As packets are received, events are posted to the event queue by Windows TCP layer and these in turn trigger methods in the FTP component.

The net effect of this is that, without threading, a single thread can support several thousand concurrent connections because you are literally tying the operating system's TCP handling directly to your application code.  This results in a highly responsive application with a minimum of lines of code, but which does not follow traditional Von-Neumann (linear) programming style.  This model is very close to the actual operating system's model of operation, which makes it very fast and reliable in Windows.  

This model is not readily portable to UNIX environments, so the kylix ICS is actually a fairly different product from the Windows ICS.  Ihe model is very different from the UNIX TCP model, so it suffers a certain amount of inefficiency in the UNIX world as compared to the Windows world.

Indy for Windows is what I call "pseudo-blocking", in the sense that it cannot truly block the thread in Windows or the TCP mechanism would stop working, but there are some gyrations in its Windows implementation code that make it appear to block the thread so von-neumann style coding can be used.  Under Windows systems, it suffers some inefficiencies and has the potential for lost events(packets) under high loading conditions.   Under UNIX systems Indy should perform very well since the UNIX model of TCP handling is blocking.

For example ...
    Indy_FTP1.Get;  // blocking call

Actually performs the entire get function, and on return your file has been received.

ICS is primarily the product of one person (Francois Piette) with input and feedback from a large base of technical users.  When there is a dispute over standards, Francois vote is the only one that counts, and his vote always follows the RFC's and Windows API standards.  

Indy is a collaborative effort under Project JEDI.  I have not been involved in its development processes, but it appears to be a representative democracy ratherthan an autocracy.  Where Francois felt that tying the Windows event model was more imporant, the consensus of Indy developers appears to have been that being able to code in a linear fashion was more important.

ICS was written and targeted at large enterprise installations with higly technical Windows programmers.  It was written in such a awy that every last bit of performance can be squeezed out of your CPU and network subsystems.  At least one site regularly tests their ICS based programs with 16,000 concurrent connections supported by one thread.

Most Delphi developers are aiming at small to tiny installations.  This probably influenced the Indy development group's decision to pursue the linear programming model over the Windows event model.  Also, my experience has been that most programmers (including Delphi programmers) are not comfortable with the free wheeling world of state engines and events.  

Hopefully a Project JEDI programmer will have more feedback on his perception of the difference between ICS and Indy.

Assisted Solution

DeerBear earned 250 total points
ID: 9660585

I personally use TServerSocket and TClientSocket :-)

Yeah, they're poor, probably inefficient, and have all the
defects you may like.

But I like them. They follow the Delphi standards and I know
that I can rely on this fact to make my code work.

As to the Indy/ICS dispute, I think it's a problem of philosophy.

I used Indy for a subproject, a COM component to send emails, and I
must say that it was quite straight-forward.

ICS has been thougth with APIs in mind, while Indy was thought with
classes in mind.

This means that an Indy class can be used in different contexts,
while an ICS one cannot.

To give you an example, imagine to develop a new kind of
newsgroup protocol.

What happens with Indy? With Indy you have a TIdMessage class
where you can start from when representing your message.

With ICS, you can't do it.

This said, I wouldn't discard another option available for
sockets under Windows/Kylix: Synapse.

Synapse is a class framework, no components.

This gives you the possibility to use it for example in
console mode applications with a very small foot-print.
Very handy.


Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Expert Comment

ID: 9660642
ICS is also usable in console app environments, and I presume that Indy is also.  All that is required is a message pump, which ICS thoughtfully provides if your app does not.

With ICS, to develop a new protocol you would develop a state engine class for the protocol to wrapper the TWSocket class.  For example, the TFTPServer and TFTPClient clases in ICS both descend directly from TObject, and they wrap the TWSocket component with application logic to support the permutations of the protocol.  ICS is entirely built around state engines, so creation of a new protocol would not be as intuitive for many people.
LVL 17

Author Comment

by:Wim ten Brink
ID: 9809669
So far the only arguments are from swift99 and DeerBear and both have pretty good arguments. Now, if no one else has some additional arguments I will call this a draw and divide the points evenly. :-)

BTW: About using the components in a console application, I guess Andrew means that the Synapse classes don't rely on the TComponent class, thus the final binary size is pretty small. (I checked the source, noticed the use of the classes unit so it will still be at least 100 KB but at least less than the 300 KB that you get by using TComponent as base class. However, the Synapse class framework inherits from TObject and I would have preferred it when it was based upon the TInterfacedObject. That would allow you to use these components by using interfaces.

One everlasting question will always be what is better, synchronous or asynchronous communications. Personally, I prefer to create a multi-threaded synchronous approach which is why I prefer Indy a bit more. The multiple threads do allow me to make things appear as if they're asynchronous. Then again, I am quite happy with using multiple threads in the first place since I'd have to write many multithreaded applications before.

Expert Comment

ID: 9810671
The answer that my associate here at work gives is that Synchronous is better because most programmers understand it better.  Maintenance is typically 4 time the cost of development over the lifetime of a product, so even small changes in approach to make maintenance easier pay for themselves quickly.

Nevertheless, we used ICS when we needed to move a lot of terabytes of data in a hurry.

The efficiency factor is not as critical with modern CPU's - your bottlenecks are latency and bandwidth rather than CPU.  Those are entirely outside of the control of applications level software, and mostly outside the control of systems level software.
LVL 17

Author Comment

by:Wim ten Brink
ID: 9816863
True, latency and bandwidth are one of our problems, although my company does have a very fast internet-connection. However, since we're developing software for other companies we do have to keep an eye on bandwidth most of the time. We don't have to move terabytes in general. We're still thinking in just megabytes for transactions. :-) And synchronous or asynchronous does not improve anything regarding to bandwidth or latency.

I did use ICS for one project, btw. And yes, asynchronous. But then a collegue of mine took over the project and he could not understand how it worked. He made some modifications and afterwards I could repair his modifications. As a result we decided to use the "simpler" Indy components since my collegue was more familiar with those. Indeed, maintenance is quite expensive, especially when less experienced developers have to work with it.

Expert Comment

ID: 9816919
Hi Alex,

As to using interfaces with them, you can simply add IInterface and
implement _AddRef and _DelRef with( respectively ) InterlockedIncrement and InterlockedDecrement.



Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

679 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question