7

I'm currently learning C# coming from a java background. To get my feet wet I decided to make a simple SMTP mail application. And I learned very quickly that C# offers support for both Synchronous and Asynchronous sockets.

From what I can see, there is no real advantage to using a synchronous socket vs an asynchronous since the latter doesn't block and therefor doesn't require you to create a new thread each time. There also doesn't seem to be a noticeable overhead to using one or the other.

So my question is this, is there an advantage to using a synchronous socket or is it better to just stick with asynchronous in most cases?

Mo H.
  • 1,726
  • 1
  • 18
  • 27
  • 1
    It all depends on the situation, i would say in 99% of cases you would use asynchronous and in the rare 1% synchronous where you want to make sure that the email is send for sure and that that block of code is finished and continue with the program after that. Also if you make your own threads for this pourpose you would also use synchronous. – Vajura Nov 11 '14 at 11:08
  • I assumed that was the case. But I also figured that you could probably do the same thing with asynchronous as well. Or am I wrong? – Mo H. Nov 11 '14 at 11:09
  • 2
    @MuhammadHijazi You can, you're right. Funcationally, there is **no** difference between using async or sync sockets whatsoever. – dcastro Nov 11 '14 at 11:13
  • Ok, perfect! Thank you! – Mo H. Nov 11 '14 at 11:14

3 Answers3

10

Async IO saves threads. A thread consumes (usually) 1MB of stack memory. This is the main reason to use async IO when the number of concurrent outstanding IO operations becomes big. According to my measurements OS scalability is not a concern until you get into the thousands of threads.

The main disadvantage is that it requires more development effort to make the same application work at the same level of reliability.

I have written about this tradeoff at length. Also: Should we switch to use async I/O by default?

It is objectively wrong advice to recommend to always use async IO.

Community
  • 1
  • 1
usr
  • 162,013
  • 33
  • 219
  • 345
9

Either mechanism will work. The main difference is that synchronous implies either blocking a thread that would otherwise do other useful things, or dedicating a thread to each connection. Either way, this does not scale very well. For simple applications with few or just one active connection, it might be okay.

But for any scenario where you need to handle any significant number of concurrent connections, the asynchronous APIs are the only ones that provide adequate performance. Also, in any interactive scenario (i.e. where you have to deal with user input and output), the asynchronous approach is more easily integrated with the user interface. That's especially true now that we have async and await in C#.

Peter Duniho
  • 62,751
  • 5
  • 84
  • 120
  • Note that for a proper implementation, synchronous APIs imply one thread for the listener socket and *two* threads per client connection. – Stephen Cleary Nov 11 '14 at 18:58
  • That depends on the application protocol. Simple request/response protocols do not require receiving and sending concurrently and can be handled in a single thread. – Peter Duniho Nov 11 '14 at 18:59
  • Only if everything is perfect. A "simple" request/response protocol cannot detect a half-open condition, requiring at the very least a timer to recover. – Stephen Cleary Nov 11 '14 at 19:02
  • Sorry...I don't know what you mean. How does having a second thread for a connection solve the half-open problem? You're still not going to detect the condition unless you try to send, and if the protocol doesn't require the local end to send until data is received, the local end would have no reason to try. Perhaps you can provide a link to a more in-depth discussion that elaborates on what you're talking about. – Peter Duniho Nov 11 '14 at 19:06
  • Sorry, I meant the protocol itself cannot detect half-open, regardless of whether it's synchronous or asynchronous. If it's synchronous, then you'd need a timer to shut down the socket (from another thread), so it's not possible to have a strictly single-threaded approach regardless of how simple the protocol is. – Stephen Cleary Nov 11 '14 at 19:14
  • Yes, that's true. There are brain-dead protocols out there that cannot detect half-open. Still, those protocols can be implemented with just a single thread per connection. :) And as far as using a timer goes, a single timer can manage multiple connections, so there'd still only need to be a single thread dedicated to each connection. – Peter Duniho Nov 11 '14 at 19:16
1

Independently of the programming language you are using, suggesting only async sockets is a bad advice. It is true that all problems can be solved using async, but not all (e.g. 100'000 connections) can be solved using synchronous ones. But most of the time, problems tend to be simpler (<100 connections).

In my experience, (mediocre) programmers tend to get lost in the mess they are creating using async sockets, whereas handling a sync socket in a separate thread is simple, understandable and more maintainable. Creating a thread under Windows is costly, assuming a proper operating system, it is much less overhead (5 us on x86 / Linux). Also it doesn't take 1 MB of RAM for a thread (at least not with a native program), but rather a few kb for stack and state (registers).

On top, a lot of people argue that synchronous socket programming is slower, but that's not always true. Context switches (to other threads) have a cost, but async socket interfaces are also not cheap for the operating system kernel.

As always: chose the solution that best fits the situation.

Thomas M.
  • 21
  • 3