Managing Socket Pools

There are many times when I need to manage a set of network connections. One situation is when I’m the ‘client’ side of a connection. Ideally, I would have a pool of connections ready to go at a moment’s notice, because TCP/IP startup times can take a while. Additionally, I’d like to reuse connections that have already been established, for the same reason. So, what to do.

I have this SocketPool construct, which manages a set of network streams (tcp/ip connections). The code looks like this:

local Collections = require "Collections"
local NetStream = require "NetStream"

local SocketPool_t = {}
local SocketPool_mt = {
  __index = SocketPool_t;

local SocketPool = function(params)
  params = params or {host="localhost", port=80, reserve=2, timeout=60*2}

  local obj = {
    Connections =;
    Hostname = or "localhost";
    Port = tonumber(params.port) or 80;
    Reserve = params.reserve or 2;
    Timeout = params.timeout,
  setmetatable(obj, SocketPool_mt);

  obj:Cycle()  -- Reserve initial set of connections
  return obj

function SocketPool_t:CreateNewConnection()
  local connection, err = NetStream.Open(self.Hostname, self.Port)

  if not connection then
    return nil, err
  return connection

function SocketPool_t:CleanoutSockets()
  local qLen = self.Connections:Len()

  -- Check each connection to see if it's still connected
  -- and if it has run past its idle time
  while qLen > 0 do
    local connection = self.Connections:Dequeue()

    qLen = qLen - 1

function SocketPool_t:Cycle()

  -- Fill back up to the reserve level
  while self.Connections:Len() < self.Reserve do
    local connection, err = self:CreateNewConnection()
    if not connection then
      return false, err
  return true

function SocketPool_t:AddConnection(connection)
  if not connection:IsConnected() or connection:IsIdle() then
    return false
  return true

function SocketPool_t:GetConnection()
  return self.Connections:Dequeue()

return SocketPool

Well, that’s a bit of a mouthful, but really it’s fairly straight forward. The usage is like this:

local sockpool = SocketPool({host="", port=80, reserve=2, timeout=120})

while running do
  local conn = sockpool:GetConnection();
  conn:Send("Hello, World");

Basically, create an instance of a socket pool, connecting to ‘’. Each time through the loop, I get a connection from the pool, do something with it, and return the connection back to the pool.

This is really convenient because the pool will take care of getting rid of the socket if it has already been closed, by either end, and creating new sockets when needed. In this particular case, I have setup the pool such that I will always have 2 sockets in reserve. That means that as long as I’m asking for one at a time, I’m always going to get a socket that’s already connected and ready to go.

I have put in a timeout of two minutes (120 seconds). That way, when I go to get a new socket, the pool will first get rid of those sockets that have been sitting around for too long. If it has fallen below the reserve mark (2), then it will refill with fresh new connections. The timeout is very useful to have because when you’re using tcp/ip based sockets out on the internet, there are numerous reasons why having a stale socket sitting around is not a good thing. So, dumping them out of your usage pool with some frequency ensures that what remains is fresh and will not suffer from various ailments such as being silently closed by some intervening router.

I’ve used a couple of things here like the NetStream, and the Queue, which aren’t standard fare, but you can get the general idea.

There is one little item that I found to be challening to really do correctly, on Win32 at least. The function: connection:IsConnected() is supposed to determine whether a tcp/ip socket is currently connected or not. On Windows, this is a surprisingly non-obvious thing to determine.

Here’s the socket code for it:

GetConnectionTime = function(self)
  local poptvalue ='int[1]')
  local poptsize ='int[1]',ffi.sizeof('int'))
  local size = ffi.sizeof('int')

  local success, err = WinSock.getsockopt(self.Handle, SOL_SOCKET, SO_CONNECT_TIME, poptvalue, poptsize)
  if not success then
    return nil, err

  return poptvalue[0];		

IsConnected = function(self)
  success, err = self:GetConnectionTime()
  if success and success >= 0 then
    return true

  return false

The key is the GetConnectionTime() function. This call will tell you how long a socket has been connected. There are two ways in which this call can fail. The first is that the socket was never actually connected to anything. In this case, getsockopt() will succeed, but the connection time will be ‘-1’. The second case is that the socket was connected at some point, but subsequently disconnected. In this case, the getsockopt() will return nil, WSAENOTSOCK (or some other error).

The IsConnected() function takes advantage of these return values, assuming the only valid state is that the connection time is greater than or equal to 0. All other cases indicate the socket is not connected.

This is a fairly quick and easy test. Perhaps a more robust situation might be to use io completion ports, and catch the state transition there. But, this is a nice quick and dirty mechanism that you can use at any time, without having to get your feet into the io completion world.

So, there you have it. Fairly easy management of client side tcp/ip connections. By using such a mechanism, my code is much more compact and clean, and I don’t have to worry about managing my socket connections.