Library tutorials & articles

Handling multiple socket read & write operations

A socket server with a business logic thread pool

Now that we have a suitable thread pool we can integrate it with our fake POP3 socket server so that the actual processing of commands can occur in the business logic pool whilst the IO pool is left to get on with the IO operations. We can also move socket closure off to the business logic pool so that we don't block the IO threads with a lingering socket close.

The first thing we need to do is create and configure our thread pool. Then we can pass a reference to it to our socket server class so that it can pass a reference to it to our IO threads.

  CThreadPool pool(
      5,                            // initial number of threads to create
      5,                            // minimum number of threads to keep in the pool
      10,                          // maximum number of threads in the pool
      5,                            // maximum number of "dormant" threads
      5000,                        // pool maintenance period (millis)
      100,                          // dispatch timeout (millis)
      10000);                      // dispatch timeout for when pool is at max threads
  pool.Start();
  CSocketServer server(
      INADDR_ANY,                  // address to listen on
      5001,                        // port to listen on
      10,                          // max number of sockets to keep in the pool
      10,                          // max number of buffers to keep in the pool
      1024,                        // buffer size
      pool);
  server.Start();

When our socket server has a complete, distinct, message to process it can dispatch it to the thread pool for processing, rather than processing it on one of its IO threads.

  void CSocketServer::ProcessCommand(
      CSocketServer::Socket *pSocket,
      CIOBuffer *pBuffer)
  {
      pSocket->AddRef();
      pBuffer->AddRef();
      m_pool.Dispatch(reinterpret_cast(pSocket), 0, pBuffer->GetAsOverlapped());
  }

Since we're passing the socket and IO buffer to another thread we have to increment their reference counts so that they dont get cleared up from underneath us. Over in our business logic thread we can finally process the message, and then release the references we took on the socket and IO buffer.

void CThreadPoolWorkerThread::Process(
  ULONG_PTR completionKey,
  DWORD operation,
  OVERLAPPED *pOverlapped)
{
  Socket *pSocket = reinterpret_cast(completionKey);
  CIOBuffer *pBuffer = CIOBuffer::FromOverlapped(pOverlapped);
 
  ProcessMessage(pSocket, pBuffer);
  pSocket->Release();
  pBuffer->Release();
}

Since the socket class marshals all IO requests back to the IO thread pool we can safely make read and write requests from our business logic thread even though the thread may be terminated before the IO requests completes.

Comments

  1. 08 May 2007 at 11:15
    It's up to you. You may select anyone you want, but better except some standart ports. Read documentation.
  2. 13 Feb 2004 at 01:46

    Hi there,


    How do I find the port of the machine for scoket connection.


    Thanks


    PPCC

  3. 01 Jan 1999 at 00:00

    This thread is for discussions of Handling multiple socket read & write operations.

Leave a comment

Sign in or Join us (it's free).

Len Holgate Len has been programming for over 20 years, having first started with a Sinclair ZX-80. Now he runs his own consulting company, JetByte Limited. JetByte provides contract programming and consultanc...

Related discussion

Related podcasts

  • Listener Feedback 67

    This mailbag episode includes FASM, scripts, sockets, SSL/TLS, HTTPS, Windows 7's XP mode, and more. Security Now wiki shownotes For 16kpbs versions, transcripts, and notes (including fixes), visit Steve's site: grc.com, also the home of the best disk maintenance and recovery utility ever written...

Want to stay in touch with what's going on? Follow us on twitter!