[Sockets] Indy or ICS?

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...
LVL 17
Wim ten BrinkSelf-employed developerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Geoff M.
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.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial

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.


Become a Certified Penetration Testing Engineer

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

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.
Wim ten BrinkSelf-employed developerAuthor Commented:
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.
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.
Wim ten BrinkSelf-employed developerAuthor Commented:
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.
Hi Alex,

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


It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.