Improve consistency of error handling

Ensure that all errors are handled in a consistent way and cap the buffer size
to prevent any chance of run-away buffers.

We had reports of cases where name resolution failed would result in a fatal exception.

I was able to track down the cause of this to not registering an `error` handler on the object returned from `net.createConnection()`.

While I was looking at the code, I identified a few cases where it would be possible for the connection retry logic to give up, so I consolidated that logic.