6

Currently, from what I've researched, there are 3 ways to work with socket asynchronously:

.Net 4.5 Async example: Using .Net 4.5 Async Feature for Socket Programming (second post)

[...]Async: http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

Begin[...]: http://msdn.microsoft.com/en-us/library/5w7b7x5f(v=vs.110).aspx

I am very confused with all the options .Net provides for working with asynchronous sockets. Why should I use one or the other? What better choice to have performance with thousands of simultaneous connections?

Community
  • 1
  • 1
Gustavo Piucco
  • 467
  • 1
  • 7
  • 17
  • 1
    Many `Task`-based socket APIs are just wrappers around Begin/End APM APIs, made with `Task.FromAsync`: http://stackoverflow.com/a/24112000/1768303 – noseratio Jun 12 '14 at 00:09

4 Answers4

10

Methods using SocketAsyncEventArgs most closely match the underlying Windows technology (I/O Completion Ports). They are essentially a bare-metal wrapper designed to perform zero allocation and extract the highest performance at the cost of a less friendly API. This has a disadvantage of more tightly coupled code as it doesn't implement any standard Stream API. The other async socket methods all wrap this one.

Methods using a Begin/End pair are using what's called the Asynchronous Programming Model (APM). APM is the original async model of .NET. It's very easy to write spaghetti code if you use it half-cocked, but it's functional and fairly simple to use once you have some experience with it. They shouldn't see much use in modern .NET, though, because we've got something far easier and better performing:

Methods returning a Task are using the Task-based Asynchronous Pattern (TAP). Tasks are a pure upgrade to APM: they're more flexible, easier to compose, and should generally have equal or better performance. When combined with language-integrated async/await, you can write code that performs great and is significantly easier to understand and maintain.

tl;dr use Task methods, unless you've got a requirement of extreme perf. Then use SocketAsyncEventArgs methods. Don't use APM methods.

Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
  • I know this answer is old, but how are the TAP methods "better performing" than APM methods when the TAP methods (at least for the networking classes) are a wrapper around the APM methods? – R1PFake Jan 25 '19 at 16:18
  • @R1PFake The TAP methods in .NET Core [wrap `SocketAsyncEventArgs` when possible](https://github.com/dotnet/corefx/blob/master/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L339). – Cory Nelson Jan 25 '19 at 17:00
7

What better choice to have performance with thousands of simultaneous connections?
...
A curiosity regarding the Begin[...]. If I have a MMORPG server where one connection interacting with each other for position update, animation, effects (basic MMORPG mechanism), in numbers, which would be "heavily loaded servers"? 200~300 simultaneous connections?

On the server side, you may benefit equally well from using any asynchronous socket APIs, either Begin/End-style APM ones, event-based EAP ones or Task-based TAP ones. That's because you'll be blocking fewer threads, as opposed to using the synchronous APIs. So, more thread will be available to concurrently serve other incoming requests to your server, thus increasing its scalability.

Most likely, your won't see any performance advantage of using TAP socket APIs over their APM or EAP analogues. However, the TAP API pattern is so much easier to develop with than APM or EAP. When used with async/await, it produces shorter, more readable and less error-prone code. You get natural pseudo-linear code flow, which is not otherwise possible with APM callbacks or EAP event handlers. If you're unable find a proper Task-based socket API, you can always make one yourself from a Begin/End APM API with Task.FromAsync (or from an EAP API, check "A reusable pattern to convert event into task").

When it comes to a client side UI app, the scalability is not that important, but there's another benefit from the TAP pattern. With little efforts, it helps making your UI responsive, because you won't be blocking the UI thread (what usually happens while waiting for the result of a synchronous call). This is not specific to Task-based Socket API, it applies to any Task-based API, e.g, Task.Delay() or Stream.ReadAsync().

For some good reading materials on asynchronous programming in C#, check the async/await tag wiki:

https://stackoverflow.com/tags/async-await/info

Community
  • 1
  • 1
noseratio
  • 59,932
  • 34
  • 208
  • 486
  • So in client side i can use TcpClient.Read synchronous to receive and send socket packets? The server sends each client a very high packet flow and clients returns in large quantities too. In this case I should use async read and send to have performance in client side? Suppose I am sending 100 packets per second in client side. – Gustavo Piucco Jun 12 '14 at 11:37
  • @GustavoPiucco, it depends on the workflow of your logic. Do you want to send all 100 packets at once, in parallel? Or 1 packet each 10ms? Do you need to receive a reply from the server before sending another packet? Etc.. – noseratio Jun 12 '14 at 11:48
  • To be exact, around 3 ~ 5 packets every 10ms. Yes, I need receive reply from server like others players positions update, monsters, npc positions and animations update etc. (MMORPG game server) – Gustavo Piucco Jun 12 '14 at 13:09
  • ...at the same time, I need to send my position, animations updates to the server respond to other players too. – Gustavo Piucco Jun 12 '14 at 13:15
  • 1
    @GustavoPiucco, yes, you'd use `async/await` and `Task`-based APIs to implement this, but you'd need to keep in mind some other things, like synchronization context and potential `ThreadPool` stuttering behavior. They're well covered here on SO. Also, I'm not a game developer to give an expert advice, but I'd look at [The Reactive Extensions (Rx)](http://msdn.microsoft.com/en-au/data/gg577609.aspx). – noseratio Jun 12 '14 at 13:57
  • In short, my next problem will be to access an object in memory from different threads due to async usage? – Gustavo Piucco Jun 12 '14 at 14:07
  • 1
    @GustavoPiucco, this again depends on your logic workflow. Asynchrony does not assume multitgreading, you may have a single-threaded main loop with custom synchronization context (google `AsyncPump`) and still use `async/await` to send/receive socket messages asynchronously and in parallel. – noseratio Jun 12 '14 at 22:20
1

If you have the chance of using .NET 4.5 and async/await, I totally recommend it.

Basically there are these ways of doing multithreading in .NET:

  1. Thread.
  2. ThreadPool.QueueWorkItem.
  3. XXXAsync method and the XXXCompleted event.
  4. BeginXXX and EndXXX methods.
  5. Task Parallel Library.
  6. async/await

The first one are raw threads, an option you should avoid because creating threads is a expensive operation. The rest, are just different ways of using the ThreadPool, that is a tool responsible of maintain a collection of threads that can be used to schedule your tasks, yielding a better performance than the first option.

The use different syntax's, but at to me, the most clear is async/await. I have created recently a WebSocket connector using sockets and asyn/await and the performance is quite good. Technically, async/await are not giving you a performance boost, but the clarity in the code will allow you to streamline the approach of your application, and that may give a good performance boost in comparison with a messy code based on continuations.

vtortola
  • 34,709
  • 29
  • 161
  • 263
  • how to asynchronousely listen if a client has sent some data (using Tasks)? i have been struggling with this and i always end up dedicating a thread to check if some thing is sent from client. Thanks in advance.. – SHM Sep 01 '16 at 08:11
  • 1
    you should have a continuous task that just listens for incoming clients. Each time you get a client, spawn a new task that operates that client and get back to listen for new clients again. In the new task, you listen for input in a continuous loop. – vtortola Sep 01 '16 at 20:58
1

First, you might want to check out this article on MSDN about what the differences between the various async programming mechanisms in .NET are.

Begin[…] was the first async socket implementation, using APM (Asynchronous Programming Model). It takes a callback as one of its arguments. While somewhat dated compared to newer methods, this works fine if you don't mind dealing with callbacks and the messy code they can create. There's also some extra overhead associated with this because of the state object, and on heavily loaded servers this can start to become a problem.

[…]Async uses the newer event based model, and is also a lighter implementation to help deal with the high traffic issues Begin[…] has. This way works nicely, but can also result in messy code if you aren't careful. Oh yea, there's a bug you can read about here, though it's likely something you won't care about unless you're building a very performant piece of software.

Task based asynchronous programming (TPL) is the newest mechanism and, with the help of the async/await keywords, can have most (if not all) of the efficiency associated with […]Async while offering much easier to understand code. Also, with Tasks, it's much easier to wait on multiple operations to finish at a time. It's important note that, while there are several native .NET functions that implement TPL and return a Task, there isn't yet one for Socket operations. There are examples of how to do this online, but it requires a bit of extra work.

cost
  • 4,420
  • 8
  • 48
  • 80
  • A curiosity regarding the Begin[...]. If I have a MMORPG server where one connection interacting with each other for position update, animation, effects (basic MMORPG mechanism), in numbers, which would be "heavily loaded servers"? 200~300 simultaneous connections? – Gustavo Piucco Jun 12 '14 at 02:16