Question

When using the Net.Sockets.TcpListener, what is the best way to handle incoming connections (.AcceptSocket) in seperate threads?

The idea is to start a new thread when a new incoming connection is accepted, while the tcplistener then stays available for further incoming connections (and for every new incoming connection a new thread is created). All communication and termination with the client that originated the connection will be handled in the thread.

Example C# of VB.NET code is appreciated.

Was it helpful?

Solution

The code that I've been using looks like this:

class Server
{
  private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);

  public void Start()
  {
    TcpListener listener = new TcpListener(IPAddress.Any, 5555);
    listener.Start();

    while(true)
    {
      IAsyncResult result =  listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
      connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event
      connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request)
    }
  }


  private void HandleAsyncConnection(IAsyncResult result)
  {
    TcpListener listener = (TcpListener)result.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(result);
    connectionWaitHandle.Set(); //Inform the main thread this connection is now handled

    //... Use your TcpClient here

    client.Close();
  }
}

OTHER TIPS

I believe you do it in the same way as any other asynchronous operation in .NET: you call the BeginXxx version of the method, in this case BeginAcceptSocket. Your callback will execute on the thread pool.

Pooled threads generally scale much better than thread-per-connection: once you get over a few tens of connections, the system works much harder in switching between threads than on getting actual work done. In addition, each thread has its own stack which is typically 1MB in size (though it depends on link flags) which has to be found in the 2GB virtual address space (on 32-bit systems); in practice this limits you to fewer than 1000 threads.

I'm not sure whether .NET's threadpool currently uses it, but Windows has a kernel object called the I/O Completion Port which assists in scalable I/O. You can associate threads with this object, and I/O requests (including accepting incoming connections) can be associated with it. When an I/O completes (e.g. a connection arrives) Windows will release a waiting thread, but only if the number of currently runnable threads (not blocked for some other reason) is less than the configured scalability limit for the completion port. Typically you'd set this to a small multiple of the number of cores.

I'd like to suggest a diffrent approach: My suggestion uses only two threads. * one thread checks for incomming connections. * When a new connection opened this info is written to a shared data structure that holds all of the current open connections. * The 2nd thread enumerate that data structure and for each open connection recieve data sent and send replys.

This solution is more scaleable thread-wise and if implemented currectly should have better performance then opening a new thread per opened connection.

There's a great example in the O'Reilly C# 3.0 Cookbook. You can download the accompanying source from http://examples.oreilly.com/9780596516109/CSharp3_0CookbookCodeRTM.zip

I would use a threadpool, this way you won't have to start a new thread every time (since this is kinda expensive). I would also not wait indefinetely for furhter connections, since clients may not close their connections. How do you plan to route the client to the same thread each time?

Sorry, don't have sample.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top