4

What is the correct way to accept sockets in a multi connection environment in .NET? Will the following be enough even if the load is high?

while (true)
{
   //block untill socket accepted
   var socket = tcpListener.AcceptSocket();
   DoStuff(socket) //e.g. spawn thread and read data
}

That is, can I accept sockets in a single thread and then handle the sockets in a thread / dataflow / whatever. So the question is just about the accept part..

7 Answers 7

1

You'll probably want the BeginAccept async operation instead of the synchroneous Accept.

And if you want to handle high load, you definitely don't want a thread per connection - again, you async methods.

Sign up to request clarification or add additional context in comments.

1 Comment

yes thats what im doing , im playing around a bit with the TPL DataFlow library and Async CTP.. but don't quite know what the best way to accept sockets are
1

Take a look at either the Reactor or Proactor pattern depending on if you wan't to block or not. I'll recommend the Patterns for Concurrent and Networked Objects book.

Comments

0

This should be fine but if the load gets even higher you might consider using the asynchronous versions of this method: BeginAcceptSocket/EndAcceptSocket.

Comments

0

The BeginAcceptSocket is a better choice if you want the most performant server.

More importantly, these async operations use a Threadpool under the hood whilst in your current implementation you are creating and destroying lots of threads which is really expensive.

Comments

0

I think the best approach is to call BeginAccept(), and within OnAccept call BeginAccept right again.. This should give you the best concurrency.

The OnAccept should be something like this:

private void OnAccept(IAsyncResult ar)
{
   bool beginAcceptCalled = false;
   try
   {
       //start the listener again
       _listener.BeginAcceptSocket(OnAccept, null);
       beginAcceptCalled = true;
       Socket socket = _listener.EndAcceptSocket(ar);
       //do something with the socket..
   }
   catch (Exception ex)
   {
       if (!beginAcceptCalled)
       {
          //try listening to connections again
          _listener.BeginAcceptSocket(OnAccept, null);
        }
    }
}

9 Comments

What? you are using the asynchronous APM methods to perform as synchronous call? This is the most inefficient use you could have, it's better to call the sync signature if you really require sync behavior (which is not what the user asking the question probably wants in a high load scenario).
@JulianDominguez where is the code above using a synchronous call?
You are calling BeginAcceptSocket, and immediately after calling EndAcceptSocket. The later call will block the thread until the async call completes. You should only call the EndXXX methods from within the completion callback
@JulianDominguez the method above is the completion callback. Notice how it's passing itself as the callback to the beginacceptsocket.
To tell you the truth, I originally didn't notice the recursive call (but that by itself doesn't make it async). Nevertheless, you are still synchronously calling the EndAcceptSocket immediately after initiating the Begin. When the callback occurs, you will be initiating a new BeginAcceptSocket and then blocking again, which is not what you want. Also, the error handling is very weird due to how you are linking these continuations.
|
0

It doesn't really matter performance wise. What matters is how you communicate which each client. That handling will consume a lot more CPU than accepting sockets.

I would use BeginAccept/EndAccept for the listener socket AND BeginReceive/EndReceive for the client sockets.

Comments

0

Since I'm using Async CTP and DataFlow, the current code looks like this:

private async void WaitForSockets()
{
    var socket = await tcpListener.AcceptSocketAsync();
    WaitForSockets();
    incomingSockets.Post(socket);
}

Note that what looks like a recursive call will not cause stack overflow or block. It will simply start a new awaiter for a new socket and exit.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.