예제 #1
0
    /** blocks until connected */
    @Override
    SelectableChannel doConnect() throws IOException, InterruptedException {
      boolean success = false;
      final SocketChannel socketChannel = SocketChannel.open();
      try {
        socketChannel.configureBlocking(false);
        socketChannel.socket().setReuseAddress(true);
        socketChannel.socket().setSoLinger(false, 0);
        socketChannel.socket().setSoTimeout(0);
        socketChannel.socket().setTcpNoDelay(true);

        try {
          socketChannel.connect(details.address());
        } catch (UnresolvedAddressException e) {
          this.connectLater();
        }

        // Under experiment, the concoction was found to be more successful if we
        // paused before registering the OP_CONNECT
        Thread.sleep(10);

        // the registration has be be run on the same thread as the selector
        addPendingRegistration(
            new Runnable() {
              @Override
              public void run() {

                final Attached attached = new Attached();
                attached.connector = ClientConnector.this;

                try {
                  socketChannel.register(selector, OP_CONNECT, attached);
                } catch (ClosedChannelException e) {
                  if (socketChannel.isOpen()) LOG.error("", e);
                }
              }
            });

        selector.wakeup();
        success = true;
        return socketChannel;

      } finally {
        if (!success) {
          try {
            try {
              socketChannel.socket().close();
            } catch (Exception e) {
              LOG.error("", e);
            }
            socketChannel.close();
          } catch (IOException e) {
            LOG.error("", e);
          }
        }
      }
    }
예제 #2
0
  /**
   * check to see if we have lost connection with the remote node and if we have attempts a
   * reconnect.
   *
   * @param key the key relating to the heartbeat that we are checking
   * @param approxTimeOutTime the approximate time in milliseconds
   * @throws ConnectException
   */
  private void heartbeatCheckHasReceived(
      @NotNull final SelectionKey key, final long approxTimeOutTime) throws ConnectException {

    final Attached attached = (Attached) key.attachment();

    // we wont attempt to reconnect the server socket
    if (attached.isServer || !attached.isHandShakingComplete()) return;

    final SocketChannel channel = (SocketChannel) key.channel();

    if (approxTimeOutTime
        > attached.entryReader.lastHeartBeatReceived + attached.remoteHeartbeatInterval) {
      if (LOG.isDebugEnabled())
        LOG.debug(
            "lost connection, attempting to reconnect. "
                + "missed heartbeat from identifier="
                + attached.remoteIdentifier);
      try {
        channel.socket().close();
        channel.close();
        activeKeys.clear(attached.remoteIdentifier);
        closeables.remove(channel);
      } catch (IOException e) {
        LOG.debug("", e);
      }

      attached.connector.connectLater();
    }
  }
예제 #3
0
  /** called when the selector receives a OP_ACCEPT message */
  private void onAccept(@NotNull final SelectionKey key) throws IOException {

    final ServerSocketChannel server = (ServerSocketChannel) key.channel();
    final SocketChannel channel = server.accept();
    channel.configureBlocking(false);
    channel.socket().setReuseAddress(true);
    channel.socket().setTcpNoDelay(true);
    channel.socket().setSoTimeout(0);
    channel.socket().setSoLinger(false, 0);

    final Attached attached = new Attached();
    channel.register(selector, OP_WRITE | OP_READ, attached);

    throttle(channel);

    attached.entryReader = new TcpSocketChannelEntryReader();
    attached.entryWriter = new TcpSocketChannelEntryWriter();

    attached.isServer = true;
    attached.entryWriter.identifierToBuffer(localIdentifier);
  }
예제 #4
0
  /** called when the selector receives a OP_CONNECT message */
  private void onConnect(@NotNull final SelectionKey key) throws IOException, InterruptedException {

    final SocketChannel channel = (SocketChannel) key.channel();
    final Attached attached = (Attached) key.attachment();

    try {
      if (!channel.finishConnect()) {
        return;
      }
    } catch (SocketException e) {
      quietClose(key, e);
      attached.connector.connect();
      throw e;
    }

    attached.connector.setSuccessfullyConnected();

    if (LOG.isDebugEnabled())
      LOG.debug(
          "successfully connected to {}, local-id={}",
          channel.socket().getInetAddress(),
          localIdentifier);

    channel.configureBlocking(false);
    channel.socket().setTcpNoDelay(true);
    channel.socket().setSoTimeout(0);
    channel.socket().setSoLinger(false, 0);

    attached.entryReader = new TcpSocketChannelEntryReader();
    attached.entryWriter = new TcpSocketChannelEntryWriter();

    key.interestOps(OP_WRITE | OP_READ);

    throttle(channel);

    // register it with the selector and store the ModificationIterator for this key
    attached.entryWriter.identifierToBuffer(localIdentifier);
  }