private void handleReads(SelectionKey sk, MemcachedNode qa) throws IOException {
   Operation currentOp = qa.getCurrentReadOp();
   ByteBuffer rbuf = qa.getRbuf();
   final SocketChannel channel = qa.getChannel();
   int read = channel.read(rbuf);
   while (read > 0) {
     getLogger().debug("Read %d bytes", read);
     rbuf.flip();
     while (rbuf.remaining() > 0) {
       assert currentOp != null : "No read operation";
       currentOp.readFromBuffer(rbuf);
       if (currentOp.getState() == OperationState.COMPLETE) {
         getLogger()
             .debug(
                 "Completed read op: %s and giving the next %d bytes",
                 currentOp, rbuf.remaining());
         Operation op = qa.removeCurrentReadOp();
         assert op == currentOp : "Expected to pop " + currentOp + " got " + op;
         currentOp = qa.getCurrentReadOp();
       }
     }
     rbuf.clear();
     read = channel.read(rbuf);
   }
 }
  /**
   * Create a client socket for the specified InetSocketAddress. Creates an SSL socket if the type
   * specified is SSL or SSL_MUTUALAUTH.
   *
   * @param type
   * @param inetSocketAddress
   * @return the socket.
   */
  public Socket createSocket(String type, InetSocketAddress inetSocketAddress) throws IOException {

    try {
      String host = inetSocketAddress.getHostName();
      int port = inetSocketAddress.getPort();
      if (_logger.isLoggable(Level.FINE)) {
        _logger.log(Level.FINE, "createSocket(" + type + ", " + host + ", " + port + ")");
      }
      if (type.equals(SSL) || type.equals(SSL_MUTUALAUTH)) {
        return createSSLSocket(host, port);
      } else {
        Socket socket = null;
        if (_logger.isLoggable(Level.FINE)) {
          _logger.log(Level.FINE, "Creating CLEAR_TEXT socket for:" + port);
        }

        if (orb.getORBData().connectionSocketType().equals(ORBConstants.SOCKETCHANNEL)) {
          SocketChannel socketChannel = ORBUtility.openSocketChannel(inetSocketAddress);
          socket = socketChannel.socket();
        } else {
          socket = new Socket(inetSocketAddress.getHostName(), inetSocketAddress.getPort());
        }

        // Disable Nagle's algorithm (i.e. always send immediately).
        socket.setTcpNoDelay(true);
        return socket;
      }
    } catch (Exception ex) {
      if (_logger.isLoggable(Level.FINE)) {
        _logger.log(Level.FINE, "Exception creating socket", ex);
      }
      throw new RuntimeException(ex);
    }
  }
 /**
  * Send the given message to the given client. The message does not need to have the length of the
  * message prepended. It is not guaranteed the message will arrive, as it can't be determined if
  * writing on a closed connection (it could appear to work). This won't be known until later when
  * get a disconnected callback is made.
  *
  * @param channelKey the key of the client to which the message should be sent.
  * @param buffer the message to send.
  */
 public void write(SelectionKey channelKey, byte[] buffer) {
   short len = (short) buffer.length;
   byte[] lengthBytes = messageLength.lengthToBytes(len);
   // copying into byte buffer is actually faster than writing to channel twice over many (>10000)
   // runs
   ByteBuffer writeBuffer = ByteBuffer.allocate(len + lengthBytes.length);
   writeBuffer.put(lengthBytes);
   writeBuffer.put(buffer);
   writeBuffer.flip();
   if (buffer != null && state.get() == State.RUNNING) {
     int bytesWritten;
     try {
       // only 1 thread can write to a channel at a time
       SocketChannel channel = (SocketChannel) channelKey.channel();
       synchronized (channel) {
         bytesWritten = channel.write(writeBuffer);
       }
       if (bytesWritten == -1) {
         resetKey(channelKey);
         disconnected(channelKey);
       }
     } catch (Exception e) {
       resetKey(channelKey);
       disconnected(channelKey);
     }
   }
 }
  /**
   * Reads incoming data from the client:
   *
   * <UL>
   *   <LI>Reads some bytes from the SocketChannel
   *   <LI>create a protocolTask, to process this data, possibly generating an answer
   *   <LI>Inserts the Task to the ThreadPool
   * </UL>
   *
   * @throws
   * @throws IOException in case of an IOException during reading
   */
  public void read() {
    // do not read if OLD.protocol has terminated. only write of pending data is
    // allowed
    if (_protocol.shouldClose()) {
      return;
    }

    SocketAddress address = _sChannel.socket().getRemoteSocketAddress();
    logger.info("Reading from " + address);

    ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);
    int numBytesRead = 0;
    try {
      numBytesRead = _sChannel.read(buf);
    } catch (IOException e) {
      numBytesRead = -1;
    }
    // is the channel closed??
    if (numBytesRead == -1) {
      // No more bytes can be read from the channel
      logger.info("client on " + address + " has disconnected");
      closeConnection();
      // tell the OLD.protocol that the connection terminated.
      _protocol.connectionTerminated();
      return;
    }

    // add the buffer to the OLD.protocol task
    buf.flip();
    _task.addBytes(buf);
    // add the OLD.protocol task to the OLD.reactor
    _data.getExecutor().execute(_task);
  }
 protected SelectableChannel getSelectableChannel(
     SocketAddress remoteAddress, SocketAddress localAddress) throws IOException {
   SocketChannel newSocketChannel = SocketChannel.open();
   Socket newSocket = newSocketChannel.socket();
   if (receiveBufferSize > 0) {
     try {
       newSocket.setReceiveBufferSize(receiveBufferSize);
     } catch (SocketException se) {
       if (logger.isLoggable(Level.FINE))
         logger.log(Level.FINE, "setReceiveBufferSize exception ", se);
     } catch (IllegalArgumentException iae) {
       if (logger.isLoggable(Level.FINE))
         logger.log(Level.FINE, "setReceiveBufferSize exception ", iae);
     }
   }
   if (sendBufferSize > 0) {
     try {
       newSocket.setSendBufferSize(sendBufferSize);
     } catch (SocketException se) {
       if (logger.isLoggable(Level.FINE))
         logger.log(Level.FINE, "setSendBufferSize exception ", se);
     } catch (IllegalArgumentException iae) {
       if (logger.isLoggable(Level.FINE))
         logger.log(Level.FINE, "setSendBufferSize exception ", iae);
     }
   }
   newSocket.setReuseAddress(reuseAddress);
   if (localAddress != null) newSocket.bind(localAddress);
   newSocketChannel.configureBlocking(false);
   return newSocketChannel;
 }
  public static void chooseDispatcher(SocketChannel channel, int op) {

    if (channel.isRegistered()) {
      for (Dispatcher dispatcher : dispatchers) {
        SelectionKey key = channel.keyFor(dispatcher.getSelector());
        if (key != null && key.isValid() && (key.interestOps() == op)) {
          return;
        }
      }

      for (Dispatcher dispatcher : dispatchers) {
        SelectionKey key = channel.keyFor(dispatcher.getSelector());
        if (key != null && key.isValid() && (key.interestOps() == 0)) {
          if (op == SelectionKey.OP_READ) {
            dispatcher.addChannelForRead(channel);
          } else if (op == SelectionKey.OP_WRITE) {
            dispatcher.addChannelForWrite(channel);
          }
          return;
        }
      }
    } else {
      if (op == SelectionKey.OP_READ) {
        nextDispatcher().addChannelForRead(channel);
      } else if (op == SelectionKey.OP_WRITE) {
        nextDispatcher().addChannelForWrite(channel);
      }
    }
  }
  public void actionHandler(SelectionKey key) throws IOException {
    if (key.isAcceptable()) {
      ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
      SocketChannel socketChannel = serverChannel.accept();
      socketChannel.configureBlocking(false);
      socketChannel.register(roller, SelectionKey.OP_READ);
    } else if (key.isReadable()) {
      ByteBuffer buffer = ByteBuffer.allocate(16);
      SocketChannel socketChannel = (SocketChannel) key.channel();
      socketChannel.read(buffer);
      buffer.flip();
      String temp = decode(buffer);
      StringBuffer strBuffer = stringLocal.get();
      if (strBuffer == null) {
        strBuffer = new StringBuffer();
      }

      strBuffer.append(temp);

      if (temp.equals("\r\n")) {
        System.out.println(strBuffer.toString());
        strBuffer = null;
      }
      stringLocal.set(strBuffer);
    }
  }
  private void listen() throws IOException {
    while (true) {
      int selec = selector.select(500);

      if (selec == 0) {
        continue;
      }

      Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
      while (iterator.hasNext()) {
        SelectionKey selectionKey = iterator.next();
        try {
          iterator.remove();

          if (selectionKey.isAcceptable()) {
            ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
            SocketChannel sc = ssc.accept();
            sc.configureBlocking(false);

            sc.register(selector, SelectionKey.OP_READ);
          } else if (selectionKey.isReadable()) {
            read(selectionKey);
          } else if (selectionKey.isWritable()) {
            write(selectionKey);
          }
        } catch (Exception e) {
          // iterator.remove(); Don't use it! It can throw a exception!
          SocketChannel sc = (SocketChannel) selectionKey.channel();
          sc.close();
        }
      }
    }
  }
  /**
   * Starts a new Thread and connects to server
   *
   * @throws IOException
   */
  public Thread connect() throws IOException {
    this.running = true;
    this.readyState = WEBSOCKET_STATE_CONNECTING;
    // open socket
    socketChannel = SocketChannel.open();
    socketChannel.configureBlocking(false);
    // set address
    socketChannel.connect(new InetSocketAddress(uri.getHost(), port));
    // start a thread to make connection

    // More info:
    // http://groups.google.com/group/android-developers/browse_thread/thread/45a8b53e9bf60d82
    // http://stackoverflow.com/questions/2879455/android-2-2-and-bad-address-family-on-socket-connect
    System.setProperty("java.net.preferIPv4Stack", "true");
    System.setProperty("java.net.preferIPv6Addresses", "false");

    selector = Selector.open();
    socketChannel.register(selector, SelectionKey.OP_CONNECT);
    Log.v("websocket", "Starting a new thread to manage data reading/writing");

    Thread th = new Thread(this);
    th.start();
    // return thread object for explicit closing, if needed
    return th;
  }
  @Override
  public Void call() throws Exception {
    ServerSocketChannel clientConnection = (ServerSocketChannel) selectionKey.channel();
    SocketChannel channel = clientConnection.accept();

    if (channel != null) {
      channel.configureBlocking(false);

      LOGGER.info(
          String.format("%s accepted client connection from %s", name, channel.getRemoteAddress()));

      try {
        final HttpRequest.HttpRequestWrapper requestWrapper = requestParser.parse(read(channel));

        MethodHandler handler =
            RequestHandlerFactory.newInstance(requestWrapper.getRequestLine().getMethod());
        HttpResponse.HttpResponseWrapper responseWrapper = handler.handle(requestWrapper);
        write(channel, responseWrapper);
      } finally {
        channel.close();
      }

      LOGGER.info(String.format("%s is done.", name));
    }

    return null;
  }
 void send(byte[] data) throws IOException {
   SocketChannel channel = (SocketChannel) key.channel();
   verboseLog("TCP write", data);
   byte[] lengthArray = new byte[2];
   lengthArray[0] = (byte) (data.length >>> 8);
   lengthArray[1] = (byte) (data.length & 0xFF);
   ByteBuffer[] buffers = new ByteBuffer[2];
   buffers[0] = ByteBuffer.wrap(lengthArray);
   buffers[1] = ByteBuffer.wrap(data);
   int nsent = 0;
   key.interestOps(SelectionKey.OP_WRITE);
   try {
     while (nsent < data.length + 2) {
       if (key.isWritable()) {
         long n = channel.write(buffers);
         if (n < 0) throw new EOFException();
         nsent += (int) n;
         if (nsent < data.length + 2 && System.currentTimeMillis() > endTime)
           throw new SocketTimeoutException();
       } else blockUntil(key, endTime);
     }
   } finally {
     if (key.isValid()) key.interestOps(0);
   }
 }
  private void read(SelectionKey key) throws IOException {
    SocketChannel socketChannel = (SocketChannel) key.channel();

    // Clear out our read buffer so it's ready for new data
    readBuffer.clear();

    // Attempt to read off the channel
    int numRead;
    try {
      numRead = socketChannel.read(readBuffer);
    } catch (IOException e) {
      key.cancel();
      socketChannel.close();

      System.out.println("Forceful shutdown");
      return;
    }

    if (numRead == -1) {
      System.out.println("Graceful shutdown");
      key.channel().close();
      key.cancel();

      return;
    }

    socketChannel.register(selector, SelectionKey.OP_WRITE);

    numMessages++;
    if (numMessages % 100000 == 0) {
      long elapsed = System.currentTimeMillis() - loopTime;
      loopTime = System.currentTimeMillis();
      System.out.println(elapsed);
    }
  }
Exemple #13
0
 /**
  * Creates a socket channel and connects it to a socket address.
  *
  * <p>This method performs a call to {@code open()} followed by a call to {@code
  * connect(SocketAddress)}.
  *
  * @param address the socket address to be connected to.
  * @return the new connected channel.
  * @throws AsynchronousCloseException if this channel is closed by another thread while this
  *     method is executing.
  * @throws ClosedByInterruptException if another thread interrupts the calling thread while this
  *     operation is executing. The calling thread will have the interrupt state set and the
  *     channel will be closed.
  * @throws UnresolvedAddressException if the address is not resolved.
  * @throws UnsupportedAddressTypeException if the address type is not supported.
  * @throws IOException if an I/O error occurs.
  */
 public static SocketChannel open(SocketAddress address) throws IOException {
   SocketChannel socketChannel = open();
   if (socketChannel != null) {
     socketChannel.connect(address);
   }
   return socketChannel;
 }
Exemple #14
0
  public void writeResponsePacket(SocketChannel socketChannel, ResponsePacket responsePacket) {
    try {
      ByteBuffer byteBuffer;
      byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);

      byte[] marshalObject = MarshalHelper.objectToBytes(responsePacket);
      byte[] marshalHeader = MarshalHelper.int32ToBytes(marshalObject.length);
      byteBuffer.clear();
      byteBuffer.put(marshalHeader);
      byteBuffer.put(marshalObject);
      byteBuffer.flip();

      // If no connection now, please ignore it (usually in async calling)
      try {
        if (socketChannel.isConnected()) {
          socketChannel.write(byteBuffer);
        }
      } catch (IOException e) {
        socketChannel.close();
      }

    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Test of a large write on a socket to understand what happens when the write is greater than the
   * combined size of the client send buffer and the server receive buffer and the server side of
   * the socket is either not accepted or already shutdown.
   *
   * @throws IOException
   * @throws InterruptedException
   */
  public void testDirectSockets_largeWrite_NotAccepted() throws IOException, InterruptedException {

    final Random r = new Random();

    // Get a socket addresss for an unused port.
    final InetSocketAddress serverAddr = new InetSocketAddress(getPort(0));

    // First our ServerSocket
    final ServerSocket ss = new ServerSocket();
    try {

      // Size of the server socket receive buffer.
      final int receiveBufferSize = ss.getReceiveBufferSize();

      // Allocate buffer twice as large as the receive buffer.
      final byte[] largeBuffer = new byte[receiveBufferSize * 10];

      if (log.isInfoEnabled()) {
        log.info(
            "receiveBufferSize=" + receiveBufferSize + ", largeBufferSize=" + largeBuffer.length);
      }

      // fill buffer with random data.
      r.nextBytes(largeBuffer);

      // bind the ServerSocket to the specified port.
      ss.bind(serverAddr);

      // Now the first Client SocketChannel
      final SocketChannel cs = SocketChannel.open();
      try {
        /*
         * Note: true if connection made. false if connection in
         * progress.
         */
        final boolean immediate = cs.connect(serverAddr);
        if (!immediate) {
          // Did not connect immediately, so finish connect now.
          if (!cs.finishConnect()) {
            fail("Did not connect.");
          }
        }

        /*
         * Attempt to write data. The server socket is not yet accepted.
         * This should hit a timeout.
         */
        assertTimeout(10L, TimeUnit.SECONDS, new WriteBufferTask(cs, ByteBuffer.wrap(largeBuffer)));

        accept(ss);

      } finally {
        cs.close();
      }

    } finally {

      ss.close();
    }
  }
  // actual connection logic
  private void _connect() throws IOException {
    // Continuous loop that is only supposed to end when "close" is called.

    selector.select();
    Set<SelectionKey> keys = selector.selectedKeys();
    Iterator<SelectionKey> i = keys.iterator();

    while (i.hasNext()) {
      SelectionKey key = i.next();
      i.remove();
      if (key.isConnectable()) {
        if (socketChannel.isConnectionPending()) {
          socketChannel.finishConnect();
        }
        socketChannel.register(selector, SelectionKey.OP_READ);
        _writeHandshake();
      }
      if (key.isReadable()) {
        try {
          _read();
        } catch (NoSuchAlgorithmException nsa) {
          this.onError(nsa);
        }
      }
    }
  }
  private void handleInput(SelectionKey key) throws IOException {

    if (key != null && key.isValid()) {

      SocketChannel sc = (SocketChannel) key.channel();
      if (key.isConnectable()) {
        if (sc.finishConnect()) {
          sc.register(selector, SelectionKey.OP_READ);
          doWrite(sc);
        } else System.exit(1);
      }

      if (key.isReadable()) {
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        int readBytes = sc.read(readBuffer);
        if (readBytes > 0) {
          readBuffer.flip();
          byte[] bytes = new byte[readBuffer.remaining()];
          readBuffer.get(bytes);
          String body = new String(bytes, "UTF-8");
          System.out.println("Now is : " + body);
          this.stop = true;
        } else if (readBytes < 0) {
          key.cancel();
          sc.close();
        } else {

        }
      }
    }
  }
  // @Override
  public boolean finishConnect() throws IOException {
    if (_socketType == SocketType.Incoming) {
      throw new IOException("Invalid State-Connect called on an Incoming (server) Socket");
    }

    if (_channel == null) {
      throw new IOException("Invalid State - finishConnect called on closed channel");
    }

    try {
      if (_channel.finishConnect()) {

        _channel.socket().setKeepAlive(true);

        // LOG.info(this + "Connected to: " + _address.getAddress().getHostAddress() + ":" +
        // _address.getPort() + " via Interface:" +
        // _channel.socket().getLocalAddress().getHostAddress());

        return true;
      }
    } catch (IOException e) {
      // LOG.error("channel.finishConnect to address:" + _address.getAddress().getHostAddress() +"
      // port: " + _address.getPort() + " threw exception:" + e.toString());
      throw e;
    }
    return false;
  }
  /** Closes the underlying sockets and socket streams. */
  @Override
  public void close() throws IOException {
    SocketChannel s = _s;
    _s = null;

    if (s != null) {
      s.close();
    }

    /*
      OutputStream os = _os;
      _os = null;

      InputStream is = _is;
      _is = null;

      try {
        if (os != null)
          os.close();

        if (is != null)
          is.close();
      } finally {
        if (s != null)
          s.close();
      }
    */
  }
 private static void setClientSocketOptions(SocketChannel channel) throws IOException {
   channel.socket().setPerformancePreferences(0, 1, 3);
   channel.socket().setTcpNoDelay(true);
   probeAndSetSize(false, 2 << 16, 2 << 10, channel);
   probeAndSetSize(true, 2 << 15, 2 << 10, channel);
   channel.configureBlocking(false);
 }
Exemple #21
0
    @JSFunction
    public static Object connect(Context cx, Scriptable thisObj, Object[] args, Function func) {
      final TCPImpl tcp = (TCPImpl) thisObj;
      String host = stringArg(args, 0);
      int port = intArg(args, 1);

      boolean success = false;
      SocketChannel newChannel = null;
      try {
        InetSocketAddress targetAddress = new InetSocketAddress(host, port);
        NetworkPolicy netPolicy = tcp.getNetworkPolicy();
        if ((netPolicy != null) && !netPolicy.allowConnection(targetAddress)) {
          log.debug("Disallowed connection to {} due to network policy", targetAddress);
          setErrno(Constants.EINVAL);
          return null;
        }

        if (log.isDebugEnabled()) {
          log.debug("Client connecting to {}:{}", host, port);
        }
        clearErrno();
        if (tcp.boundAddress == null) {
          newChannel = SocketChannel.open();
        } else {
          newChannel = SocketChannel.open(tcp.boundAddress);
        }
        tcp.clientChannel = newChannel;
        getRunner().registerCloseable(newChannel);
        tcp.clientInit();
        tcp.clientChannel.connect(targetAddress);
        tcp.selKey =
            tcp.clientChannel.register(
                getRunner().getSelector(),
                SelectionKey.OP_CONNECT,
                new SelectorHandler() {
                  @Override
                  public void selected(SelectionKey key) {
                    tcp.clientSelected(key);
                  }
                });

        tcp.pendingConnect = (PendingOp) cx.newObject(thisObj, PendingOp.CLASS_NAME);
        success = true;
        return tcp.pendingConnect;

      } catch (IOException ioe) {
        log.debug("Error on connect: {}", ioe);
        setErrno(Constants.EIO);
        return null;
      } finally {
        if (!success && (newChannel != null)) {
          getRunner().unregisterCloseable(newChannel);
          try {
            newChannel.close();
          } catch (IOException ioe) {
            log.debug("Error closing channel that might be closed: {}", ioe);
          }
        }
      }
    }
    private void doConnect(SelectionKey key) {
      SocketChannel sc = (SocketChannel) key.channel();
      TCConnectionImpl conn = (TCConnectionImpl) key.attachment();

      try {
        if (sc.finishConnect()) {
          sc.register(selector, SelectionKey.OP_READ, conn);
          conn.finishConnect();
        } else {
          String errMsg = "finishConnect() returned false, but no exception thrown";

          if (logger.isInfoEnabled()) {
            logger.info(errMsg);
          }

          conn.fireErrorEvent(new Exception(errMsg), null);
        }
      } catch (IOException ioe) {
        if (logger.isInfoEnabled()) {
          logger.info("IOException attempting to finish socket connection", ioe);
        }

        conn.fireErrorEvent(ioe, null);
      }
    }
  /** Handle new OP_CONNECT ops. */
  protected void onConnectOp(Context ctx, ConnectChannelOperation selectionKeyOp)
      throws IOException {
    SocketChannel socketChannel = (SocketChannel) selectionKeyOp.getChannel();
    SocketAddress remoteAddress = selectionKeyOp.getRemoteAddress();
    CallbackHandler callbackHandler = selectionKeyOp.getCallbackHandler();

    CallbackHandlerSelectionKeyAttachment attachment =
        new CallbackHandlerSelectionKeyAttachment(callbackHandler);

    SelectionKey key = socketChannel.register(selector, 0, attachment);
    attachment.associateKey(key);

    boolean isConnected;
    try {
      isConnected = socketChannel.connect(remoteAddress);
    } catch (Exception e) {
      if (logger.isLoggable(Level.FINE)) {
        logger.log(Level.FINE, "Exception occured when tried to connect socket", e);
      }

      // set isConnected to true to let callback handler to know about the problem happened
      isConnected = true;
    }

    // if channel was connected immediately or exception occured
    if (isConnected) {
      onConnectInterest(key, ctx);
    } else {
      key.interestOps(SelectionKey.OP_CONNECT);
    }
  }
Exemple #24
0
 private void reconnect() {
   FVLog.log(LogLevel.INFO, this, "trying to reconnect to ", this.hostname, ":", this.port);
   // reset our state to unconnected (might be a NOOP)
   this.isConnected = false;
   this.msgStream = null;
   // try to connect socket to controller
   try {
     if (this.sock != null)
       // note that this automatically unregisters from selector
       this.sock.close();
     this.sock = SocketChannel.open();
     sock.configureBlocking(false); // set to non-blocking
     InetSocketAddress addr = new InetSocketAddress(hostname, port);
     if (addr.isUnresolved()) {
       FVLog.log(LogLevel.INFO, this, "retrying: failed to resolve hostname: ", hostname);
       this.reconnectLater();
       return;
     }
     this.isConnected = this.sock.connect(addr); // try to connect
     // register into event loop
     this.loop.register(this.sock, SelectionKey.OP_CONNECT, this);
   } catch (IOException e) {
     FVLog.log(LogLevel.CRIT, this, "Trying to reconnect; trying later; got : ", e);
     this.reconnectLater();
   }
 }
 /**
  * attempts to send data to the client<br>
  * if all the data has been successfully sent, the ConnectionHandler will automatically switch to
  * read only mode, otherwise it'll stay in it's current mode (which is read / write).
  *
  * @throws IOException if the write operation fails
  * @throws ClosedChannelException if the channel have been closed while registering to the
  *     Selector
  */
 public synchronized void write() {
   if (_outData.size() == 0) {
     // if nothing left in the output string, go back to read mode
     switchToReadOnlyMode();
     return;
   }
   // if there is something to send
   ByteBuffer buf = _outData.remove(0);
   if (buf.remaining() != 0) {
     try {
       _sChannel.write(buf);
     } catch (IOException e) {
       // this should never happen.
       e.printStackTrace();
     }
     // check if the buffer contains more data
     if (buf.remaining() != 0) {
       _outData.add(0, buf);
     }
   }
   // check if the OLD.protocol indicated close.
   if (_protocol.shouldClose()) {
     switchToWriteOnlyMode();
     if (buf.remaining() == 0) {
       closeConnection();
       SocketAddress address = _sChannel.socket().getRemoteSocketAddress();
       logger.info("disconnecting client on " + address);
     }
   }
 }
Exemple #26
0
  /** Check for new client connections */
  private void acceptNewConnections() {

    try {
      SocketChannel clientChannel;
      // since sSockChan is non-blocking, this will return immediately
      // regardless of whether there is a connection available
      while ((clientChannel = sSockChan.accept()) != null) {
        if (getContext().getServer().isRedirectActive()) {
          LOG.debug(
              "Client redirected to {}: {}",
              getContext().getServer().getRedirectAddress().getHostAddress(),
              clientChannel.socket().getInetAddress().getHostAddress());
          redirectAndKill(clientChannel.socket());
          continue;
        }

        Client client =
            getContext().getClients().addNewClient(clientChannel, readSelector, SEND_BUFFER_SIZE);
        if (client == null) {
          continue;
        }

        // from this point on, we know that client
        // has been successfully connected
        client.sendWelcomeMessage();

        LOG.debug("New client connected: {}", client.getIp().getHostAddress());
      }
    } catch (Exception ex) {
      LOG.error("Exception in acceptNewConnections(): " + ex.getMessage(), ex);
    }
  }
  /**
   * Start the server running - accepting connections, receiving messages. If the server is already
   * running, it will not be started again. This method is designed to be called in its own thread
   * and will not return until the server is stopped.
   *
   * @throws RuntimeException if the server fails
   */
  public void run() {
    // ensure that the server is not started twice
    if (!state.compareAndSet(State.STOPPED, State.RUNNING)) {
      started(true);
      return;
    }

    Selector selector = null;
    ServerSocketChannel server = null;
    try {
      selector = Selector.open();
      server = ServerSocketChannel.open();
      server.socket().bind(new InetSocketAddress(port));
      server.configureBlocking(false);
      server.register(selector, SelectionKey.OP_ACCEPT);
      started(false);
      while (state.get() == State.RUNNING) {
        selector.select(100); // check every 100ms whether the server has been requested to stop
        for (Iterator<SelectionKey> it = selector.selectedKeys().iterator(); it.hasNext(); ) {
          SelectionKey key = it.next();
          try {
            // remove key from the ready list
            it.remove();
            if (key.isConnectable()) {
              ((SocketChannel) key.channel()).finishConnect();
            }
            if (key.isAcceptable()) {
              // accept connection
              SocketChannel client = server.accept();
              client.configureBlocking(false);
              client.socket().setTcpNoDelay(true);
              // channel is registered for further events such as read or write
              SelectionKey acceptKey = client.register(selector, SelectionKey.OP_READ);
              connection(acceptKey);
            }
            if (key.isReadable()) {
              for (ByteBuffer message : readIncomingMessage(key)) {
                messageReceived(message, key);
              }
            }
          } catch (IOException ioe) {
            resetKey(key);
            disconnected(key);
          }
        }
      }
    } catch (Throwable e) {
      throw new RuntimeException("Server failure: " + e.getMessage());
    } finally {
      try {
        selector.close();
        server.socket().close();
        server.close();
        state.set(State.STOPPED);
        stopped();
      } catch (Exception e) {
        // do nothing - server failed
      }
    }
  }
  public static void main(String[] args) throws IOException {
    SocketChannel socketChannel = SocketChannel.open();

    // 如果设置非阻塞模式,就可以在异步模式下调用connect(), read() 和write()了。可以进一步和Selector配合。之后章节会涉及
    // socketChannel.configureBlocking(false);
    // 这个需要127.0.0.1的9999端口有进程在监听了,之后会将用ServerSocketChannel监听端口,做服务端
    socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
    ByteBuffer buf = ByteBuffer.allocate(48);

    // 剩下的读写都可以参考fileChannel

    // 非阻塞模式时候可以如下等待
    // while(! socketChannel.finishConnect() ){
    // wait, or do something else...
    // }

    // 读取数据
    //		int bytesRead = socketChannel.read(buf);
    //		System.out.println(bytesRead);

    // 写入数据
    String newData = "New String to write to file..." + System.currentTimeMillis();
    buf.clear();
    buf.put(newData.getBytes());
    buf.flip();
    System.out.println("Start send message");
    while (buf.hasRemaining()) {
      socketChannel.write(buf);
    }
    System.out.println("Finish send");
  }
 public void handleAccept(SelectionKey key) throws IOException {
   ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
   SocketChannel socketChannel = serverSocketChannel.accept();
   log.info("Server: accept client socket " + socketChannel);
   socketChannel.configureBlocking(false);
   socketChannel.register(key.selector(), SelectionKey.OP_READ);
 }
Exemple #30
0
 public SocketChannel getClientChannel(final boolean noTearDown) throws IOException {
   final List<String> listeners = m_config.getListenerAddresses();
   final Random r = new Random();
   final String listener = listeners.get(r.nextInt(listeners.size()));
   byte[] hashedPassword = ConnectionUtil.getHashedPassword(m_password);
   HostAndPort hNp = HostAndPort.fromString(listener);
   int port = Constants.DEFAULT_PORT;
   if (hNp.hasPort()) {
     port = hNp.getPort();
   }
   final SocketChannel channel =
       (SocketChannel)
           ConnectionUtil.getAuthenticatedConnection(
               hNp.getHostText(),
               m_username,
               hashedPassword,
               port,
               null,
               ClientAuthHashScheme.getByUnencodedLength(hashedPassword.length))[0];
   channel.configureBlocking(true);
   if (!noTearDown) {
     synchronized (m_clientChannels) {
       m_clientChannels.add(channel);
     }
   }
   return channel;
 }