Roger Johansson
Roger Johansson

Reputation: 23214

.NET TcpSocket programming

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

Upvotes: 4

Views: 1482

Answers (7)

Roger Johansson
Roger Johansson

Reputation: 23214

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.

Upvotes: 0

jgauffin
jgauffin

Reputation: 101130

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.

Upvotes: 0

Can Gencer
Can Gencer

Reputation: 8885

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);
        }
    }
}

Upvotes: 0

Victor Parmar
Victor Parmar

Reputation: 5779

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.

Upvotes: 0

Simon Stender Boisen
Simon Stender Boisen

Reputation: 3431

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.

Upvotes: 1

snemarch
snemarch

Reputation: 5008

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.

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

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

Upvotes: 0

Related Questions