private void read() {
        try {

            int bytesRead = 0;
            int bytes, limit, pos, size;

            // clear buffer
            _buffer.clear();

            // read first message size
            do {
                if((bytes = _socketChannel.read(_buffer)) < 0) {
                    _LOGGER.log(Level.FINE, "Message size bytes: " + bytes);
                    _socketChannel.close();
                    return;
                }
                bytesRead += bytes;
            } while(bytesRead < 4);

            // safe buffer limit and pos
            limit = _buffer.limit();
            pos = _buffer.position();

            // read message size from buffer
            _buffer.flip();
            size = _buffer.getInt() + 4;

            // restore limit and pos
            _buffer.limit(limit);
            _buffer.position(pos);

            // read more from the network..
            while(bytesRead < size){
                if((bytes = _socketChannel.read(_buffer)) < 0) {
                    _LOGGER.log(Level.FINE, "Message rest bytes: " + bytes);
                    _socketChannel.close();
                    return;
                }
                bytesRead += bytes;
            }

            // submit a client to the executor service
            _buffer.flip();
            _buffer.position(4);

            long startTime = System.nanoTime();
            _executor.submit(new Connection(startTime, _buffer,
                    // register the write back callback
                    new Callback() {
                        @Override
                        public void callback() {
                            _LOGGER.log(Level.FINE, "Calling callback");
                            _key.interestOps(SelectionKey.OP_WRITE);
                            _selector.wakeup();
                            _LOGGER.log(Level.FINE, "Interest ops set");
                        }
                    }));
        } catch (IOException e) {
            _LOGGER.log(Level.SEVERE, "Could not read from socket channel");
            throw new RuntimeException(e);
        }
    }