Beispiel #1
0
 protected void handleClient(SelectionKey key) throws IOException {
   SocketChannel sc = (SocketChannel) key.channel();
   ClientInfo ci = (ClientInfo) allClients.get(sc);
   if (ci == null) throw new IllegalStateException("Unknown client");
   if (key.isWritable()) send(sc, ci);
   if (key.isReadable())
     // 从一个客户端读进所有的可用数据
     recv(sc, ci);
 }
Beispiel #2
0
  static void test() throws Exception {
    ServerSocketChannel ssc = null;
    SocketChannel sc = null;
    SocketChannel peer = null;
    try {
      ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));

      // loopback connection
      InetAddress lh = InetAddress.getLocalHost();
      sc = SocketChannel.open(new InetSocketAddress(lh, ssc.socket().getLocalPort()));
      peer = ssc.accept();

      // peer sends message so that "sc" will be readable
      int n = peer.write(ByteBuffer.wrap("Hello".getBytes()));
      assert n > 0;

      sc.configureBlocking(false);

      Selector selector = Selector.open();
      SelectionKey key = sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

      boolean done = false;
      int failCount = 0;
      while (!done) {
        int nSelected = selector.select();
        if (nSelected > 0) {
          if (nSelected > 1) throw new RuntimeException("More than one channel selected");
          Set<SelectionKey> keys = selector.selectedKeys();
          Iterator<SelectionKey> iterator = keys.iterator();
          while (iterator.hasNext()) {
            key = iterator.next();
            iterator.remove();
            if (key.isWritable()) {
              failCount++;
              if (failCount > 10) throw new RuntimeException("Test failed");
              Thread.sleep(250);
            }
            if (key.isReadable()) {
              done = true;
            }
          }
        }
      }
    } finally {
      if (peer != null) peer.close();
      if (sc != null) sc.close();
      if (ssc != null) ssc.close();
    }
  }
  void processIO() {
    Iterator<SelectionKey> it = mySelector.selectedKeys().iterator();
    while (it.hasNext()) {
      SelectionKey k = it.next();
      it.remove();

      if (k.isConnectable()) isConnectable(k);
      else if (k.isAcceptable()) isAcceptable(k);
      else {
        if (k.isWritable()) isWritable(k);

        if (k.isReadable()) isReadable(k);
      }
    }
  }
  void isReadable(SelectionKey k) {
    EventableChannel ec = (EventableChannel) k.attachment();
    long b = ec.getBinding();

    if (ec.isWatchOnly()) {
      if (ec.isNotifyReadable()) eventCallback(b, EM_CONNECTION_NOTIFY_READABLE, null);
    } else {
      myReadBuffer.clear();

      try {
        ec.readInboundData(myReadBuffer);
        myReadBuffer.flip();
        if (myReadBuffer.limit() > 0) {
          if (ProxyConnections != null) {
            EventableChannel target = ProxyConnections.get(b);
            if (target != null) {
              ByteBuffer myWriteBuffer = ByteBuffer.allocate(myReadBuffer.limit());
              myWriteBuffer.put(myReadBuffer);
              myWriteBuffer.flip();
              target.scheduleOutboundData(myWriteBuffer);
            } else {
              eventCallback(b, EM_CONNECTION_READ, myReadBuffer);
            }
          } else {
            eventCallback(b, EM_CONNECTION_READ, myReadBuffer);
          }
        }
      } catch (IOException e) {
        UnboundConnections.add(b);
      }
    }
  }
Beispiel #5
0
  public void run() {
    try {
      SocketChannel sc = SocketChannel.open();
      InetSocketAddress sinaAddr = new InetSocketAddress("sina.com", 80);
      sc.socket().connect(sinaAddr);

      // init a selector via helper class selector provider
      Selector aSel = SelectorProvider.provider().openSelector();

      Socket soc = new Socket("host", 80);
      soc.getChannel().register(aSel, SelectionKey.OP_ACCEPT);

      // init a channel for server socket. method 1
      ServerSocketChannel ssc = ServerSocketChannel.open();
      ssc.configureBlocking(true);

      // method 2, get server socket first, then init its channel
      ServerSocket ss = new ServerSocket();
      ServerSocketChannel ssc2 = ss.getChannel();

      // set socket channel as non blocking.
      ssc.configureBlocking(false);

      InetSocketAddress isa = new InetSocketAddress("localhost", 9999);
      ssc.socket().bind(isa);

      SelectionKey acceptKey = ssc.register(aSel, SelectionKey.OP_ACCEPT);
      int keysAdded = 0;
      while ((keysAdded = aSel.select()) > 0) {
        Set readyKeys = aSel.selectedKeys();
        Iterator i = readyKeys.iterator();
        while (i.hasNext()) {
          SelectionKey sk = (SelectionKey) i.next();
          i.remove();
          ServerSocketChannel n = (ServerSocketChannel) sk.channel();
          // now we got a new socket and its channel after accept in server
          Socket s = n.accept().socket();
          SocketChannel socketChannel = s.getChannel();
          socketChannel.register(aSel, SelectionKey.OP_READ);
        }
      }
    } catch (Exception e) {

    }
  }
  public void handle(SelectionKey sk) throws IOException {
    try {

      if (request == null) {
        if (!receive(sk)) return;
        rbb.flip();
        if (parse()) build();
        try {
          reply.prepare();
        } catch (IOException x) {
          reply.release();
          reply = new Reply(Reply.Code.NOT_FOUND, new StringContent(x));
          reply.prepare();
        }
        if (send()) {
          // More bytes remain to be written
          sk.interestOps(SelectionKey.OP_WRITE);
        } else {
          // Reply completely written; we're done
          if (cio.shutdown()) {
            cio.close();
            reply.release();
          }
        }
      } else {
        if (!send()) { // Should be rp.send()
          if (cio.shutdown()) {
            cio.close();
            reply.release();
          }
        }
      }
    } catch (IOException x) {
      String m = x.getMessage();
      if (!m.equals("Broken pipe") && !m.equals("Connection reset by peer")) {
        System.err.println("RequestHandler: " + x.toString());
      }

      try {
        /*
         * We had a failure here, so we'll try to be nice
         * before closing down and send off a close_notify,
         * but if we can't get the message off with one try,
         * we'll just shutdown.
         */
        cio.shutdown();
      } catch (IOException e) {
        // ignore
      }

      cio.close();
      if (reply != null) {
        reply.release();
      }
    }
  }
  void isConnectable(SelectionKey k) {
    EventableSocketChannel ec = (EventableSocketChannel) k.attachment();
    long b = ec.getBinding();

    try {
      if (ec.finishConnecting()) eventCallback(b, EM_CONNECTION_COMPLETED, null);
      else UnboundConnections.add(b);
    } catch (IOException e) {
      UnboundConnections.add(b);
    }
  }
Beispiel #8
0
  /** Selects on sockets and informs their Communicator when there is something to do. */
  public void communicate(int timeout) {

    try {
      selector.select(timeout);
    } catch (IOException e) {
      // Not really sure why/when this happens yet
      return;
    }

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

    while (keys.hasNext()) {
      SelectionKey key = keys.next();
      keys.remove();
      if (!key.isValid()) continue; // WHY
      Communicator communicator = (Communicator) key.attachment();

      if (key.isReadable()) communicator.onReadable();
      if (key.isWritable()) communicator.onWritable();
      if (key.isAcceptable()) communicator.onAcceptable();
    }

    // Go through the queue and handle each communicator
    while (!queue.isEmpty()) {
      Communicator c = queue.poll();
      c.onMemo();
    }
  }
  void isAcceptable(SelectionKey k) {
    ServerSocketChannel ss = (ServerSocketChannel) k.channel();
    SocketChannel sn;
    long b;

    for (int n = 0; n < 10; n++) {
      try {
        sn = ss.accept();
        if (sn == null) break;
      } catch (IOException e) {
        e.printStackTrace();
        k.cancel();

        ServerSocketChannel server = Acceptors.remove(k.attachment());
        if (server != null)
          try {
            server.close();
          } catch (IOException ex) {
          }
        ;
        break;
      }

      try {
        sn.configureBlocking(false);
      } catch (IOException e) {
        e.printStackTrace();
        continue;
      }

      b = createBinding();
      EventableSocketChannel ec = new EventableSocketChannel(sn, b, mySelector);
      Connections.put(b, ec);
      NewConnections.add(b);

      eventCallback(((Long) k.attachment()).longValue(), EM_CONNECTION_ACCEPTED, null, b);
    }
  }
  public void processSelectedKeys() throws IOException {
    // 处理连接就绪事件
    for (Iterator it = selector.selectedKeys().iterator(); it.hasNext(); ) {
      SelectionKey selectionKey = (SelectionKey) it.next();
      it.remove();

      Target target = (Target) selectionKey.attachment();
      SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

      try {
        if (socketChannel.finishConnect()) {
          selectionKey.cancel();
          target.connectFinish = System.currentTimeMillis();
          socketChannel.close();
          addFinishedTarget(target);
        }
      } catch (IOException x) {
        socketChannel.close();
        target.failure = x;
        addFinishedTarget(target);
      }
    }
  }
  void isWritable(SelectionKey k) {
    EventableChannel ec = (EventableChannel) k.attachment();
    long b = ec.getBinding();

    if (ec.isWatchOnly()) {
      if (ec.isNotifyWritable()) eventCallback(b, EM_CONNECTION_NOTIFY_WRITABLE, null);
    } else {
      try {
        if (!ec.writeOutboundData()) UnboundConnections.add(b);
      } catch (IOException e) {
        UnboundConnections.add(b);
      }
    }
  }
Beispiel #12
0
    void processSelectedKeys() throws IOException {
      for (Iterator i = sel.selectedKeys().iterator(); i.hasNext(); ) {

        SelectionKey sk = (SelectionKey) i.next();
        i.remove();

        Target t = (Target) sk.attachment();
        SocketChannel sc = (SocketChannel) sk.channel();

        try {
          if (sc.finishConnect()) {
            sk.cancel();
            t.connectFinish = System.currentTimeMillis();
            sc.close();
            printer.add(t);
          }
        } catch (IOException x) {
          sc.close();
          t.failure = x;
          printer.add(t);
        }
      }
    }
Beispiel #13
0
  void isReadable(SelectionKey k) {
    EventableChannel ec = (EventableChannel) k.attachment();
    long b = ec.getBinding();

    if (ec.isWatchOnly()) {
      if (ec.isNotifyReadable()) eventCallback(b, EM_CONNECTION_NOTIFY_READABLE, null);
    } else {
      myReadBuffer.clear();

      try {
        ec.readInboundData(myReadBuffer);
        myReadBuffer.flip();
        if (myReadBuffer.limit() > 0) eventCallback(b, EM_CONNECTION_READ, myReadBuffer);
      } catch (IOException e) {
        UnboundConnections.add(b);
      }
    }
  }
  private void go() throws IOException {
    // Create a new selector
    Selector selector = Selector.open();

    // Open a listener on each port, and register each one
    // with the selector
    for (int i = 0; i < ports.length; ++i) {
      ServerSocketChannel ssc = ServerSocketChannel.open();
      ssc.configureBlocking(false);
      ServerSocket ss = ssc.socket();
      InetSocketAddress address = new InetSocketAddress(ports[i]);
      ss.bind(address);

      SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);

      System.out.println("Going to listen on " + ports[i]);
    }

    while (true) {
      int num = selector.select();

      Set selectedKeys = selector.selectedKeys();
      Iterator it = selectedKeys.iterator();

      while (it.hasNext()) {
        SelectionKey key = (SelectionKey) it.next();

        if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
          // Accept the new connection
          ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
          SocketChannel sc = ssc.accept();
          sc.configureBlocking(false);

          // Add the new connection to the selector
          SelectionKey newKey = sc.register(selector, SelectionKey.OP_READ);
          it.remove();

          System.out.println("Got connection from " + sc);
        } else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
          // Read the data
          SocketChannel sc = (SocketChannel) key.channel();

          // Echo data
          int bytesEchoed = 0;
          while (true) {
            echoBuffer.clear();

            int r = sc.read(echoBuffer);

            if (r <= 0) {
              break;
            }

            echoBuffer.flip();

            sc.write(echoBuffer);
            bytesEchoed += r;
          }

          System.out.println("Echoed " + bytesEchoed + " from " + sc);

          it.remove();
        }
      }

      // System.out.println( "going to clear" );
      //      selectedKeys.clear();
      // System.out.println( "cleared" );
    }
  }
Beispiel #15
0
  /*
   * Perform any handshaking processing.
   * <P>
   * If a SelectionKey is passed, register for selectable
   * operations.
   * <P>
   * In the blocking case, our caller will keep calling us until
   * we finish the handshake.  Our reads/writes will block as expected.
   * <P>
   * In the non-blocking case, we just received the selection notification
   * that this channel is ready for whatever the operation is, so give
   * it a try.
   * <P>
   * return:
   *		true when handshake is done.
   *		false while handshake is in progress
   */
  boolean doHandshake(SelectionKey sk) throws IOException {

    SSLEngineResult result;

    if (initialHSComplete) {
      return initialHSComplete;
    }

    /*
     * Flush out the outgoing buffer, if there's anything left in
     * it.
     */
    if (outNetBB.hasRemaining()) {

      if (!tryFlush(outNetBB)) {
        return false;
      }

      // See if we need to switch from write to read mode.

      switch (initialHSStatus) {

          /*
           * Is this the last buffer?
           */
        case FINISHED:
          initialHSComplete = true;
          // Fall-through to reregister need for a Read.

        case NEED_UNWRAP:
          if (sk != null) {
            sk.interestOps(SelectionKey.OP_READ);
          }
          break;
      }

      return initialHSComplete;
    }

    switch (initialHSStatus) {
      case NEED_UNWRAP:
        if (sc.read(inNetBB) == -1) {
          sslEngine.closeInbound();
          return initialHSComplete;
        }

        needIO:
        while (initialHSStatus == HandshakeStatus.NEED_UNWRAP) {
          resizeRequestBB(); // expected room for unwrap
          inNetBB.flip();
          result = sslEngine.unwrap(inNetBB, requestBB);
          inNetBB.compact();

          initialHSStatus = result.getHandshakeStatus();

          switch (result.getStatus()) {
            case OK:
              switch (initialHSStatus) {
                case NOT_HANDSHAKING:
                  throw new IOException("Not handshaking during initial handshake");

                case NEED_TASK:
                  initialHSStatus = doTasks();
                  break;

                case FINISHED:
                  initialHSComplete = true;
                  break needIO;
              }

              break;

            case BUFFER_UNDERFLOW:
              // Resize buffer if needed.
              netBBSize = sslEngine.getSession().getPacketBufferSize();
              if (netBBSize > inNetBB.capacity()) {
                resizeResponseBB();
              }

              /*
               * Need to go reread the Channel for more data.
               */
              if (sk != null) {
                sk.interestOps(SelectionKey.OP_READ);
              }
              break needIO;

            case BUFFER_OVERFLOW:
              // Reset the application buffer size.
              appBBSize = sslEngine.getSession().getApplicationBufferSize();
              break;

            default: // CLOSED:
              throw new IOException("Received" + result.getStatus() + "during initial handshaking");
          }
        } // "needIO" block.

        /*
         * Just transitioned from read to write.
         */
        if (initialHSStatus != HandshakeStatus.NEED_WRAP) {
          break;
        }

        // Fall through and fill the write buffers.

      case NEED_WRAP:
        /*
         * The flush above guarantees the out buffer to be empty
         */
        outNetBB.clear();
        result = sslEngine.wrap(hsBB, outNetBB);
        outNetBB.flip();

        initialHSStatus = result.getHandshakeStatus();

        switch (result.getStatus()) {
          case OK:
            if (initialHSStatus == HandshakeStatus.NEED_TASK) {
              initialHSStatus = doTasks();
            }

            if (sk != null) {
              sk.interestOps(SelectionKey.OP_WRITE);
            }

            break;

          default: // BUFFER_OVERFLOW/BUFFER_UNDERFLOW/CLOSED:
            throw new IOException("Received" + result.getStatus() + "during initial handshaking");
        }
        break;

      default: // NOT_HANDSHAKING/NEED_TASK/FINISHED
        throw new RuntimeException("Invalid Handshaking State" + initialHSStatus);
    } // switch

    return initialHSComplete;
  }
    public void run() {
      // Here's where everything happens. The select method will
      // return when any operations registered above have occurred, the
      // thread has been interrupted, etc.
      try {
        while (!stop) {
          try {
            if (selector.select() > 0) {
              if (stop) {
                break;
              }
              // Someone is ready for I/O, get the ready keys
              Set readyKeys = selector.selectedKeys();
              Iterator it = readyKeys.iterator();

              // Walk through the ready keys collection and process date requests.
              while (it.hasNext()) {
                SelectionKey sk = (SelectionKey) it.next();
                it.remove();
                SocketChannel readChannel = null;
                TcpAddress incomingAddress = null;
                if (sk.isAcceptable()) {
                  // The key indexes into the selector so you
                  // can retrieve the socket that's ready for I/O
                  ServerSocketChannel nextReady = (ServerSocketChannel) sk.channel();
                  // Accept the date request and send back the date string
                  Socket s = nextReady.accept().socket();
                  readChannel = s.getChannel();
                  readChannel.configureBlocking(false);
                  readChannel.register(selector, SelectionKey.OP_READ);

                  incomingAddress = new TcpAddress(s.getInetAddress(), s.getPort());
                  SocketEntry entry = new SocketEntry(incomingAddress, s);
                  sockets.put(incomingAddress, entry);
                  timeoutSocket(entry);
                  TransportStateEvent e =
                      new TransportStateEvent(
                          DefaultTcpTransportMapping.this,
                          incomingAddress,
                          TransportStateEvent.STATE_CONNECTED,
                          null);
                  fireConnectionStateChanged(e);
                } else if (sk.isReadable()) {
                  readChannel = (SocketChannel) sk.channel();
                  incomingAddress =
                      new TcpAddress(
                          readChannel.socket().getInetAddress(), readChannel.socket().getPort());
                } else if (sk.isWritable()) {
                  try {
                    SocketEntry entry = (SocketEntry) sk.attachment();
                    SocketChannel sc = (SocketChannel) sk.channel();
                    if (entry != null) {
                      writeMessage(entry, sc);
                    }
                  } catch (IOException iox) {
                    if (logger.isDebugEnabled()) {
                      iox.printStackTrace();
                    }
                    logger.warn(iox);
                    TransportStateEvent e =
                        new TransportStateEvent(
                            DefaultTcpTransportMapping.this,
                            incomingAddress,
                            TransportStateEvent.STATE_DISCONNECTED_REMOTELY,
                            iox);
                    fireConnectionStateChanged(e);
                    sk.cancel();
                  }
                } else if (sk.isConnectable()) {
                  try {
                    SocketEntry entry = (SocketEntry) sk.attachment();
                    SocketChannel sc = (SocketChannel) sk.channel();
                    if ((!sc.isConnected()) && (sc.finishConnect())) {
                      sc.configureBlocking(false);
                      logger.debug("Connected to " + entry.getPeerAddress());
                      // make sure conncetion is closed if not used for timeout
                      // micro seconds
                      timeoutSocket(entry);
                      sc.register(selector, SelectionKey.OP_WRITE, entry);
                    }
                    TransportStateEvent e =
                        new TransportStateEvent(
                            DefaultTcpTransportMapping.this,
                            incomingAddress,
                            TransportStateEvent.STATE_CONNECTED,
                            null);
                    fireConnectionStateChanged(e);
                  } catch (IOException iox) {
                    if (logger.isDebugEnabled()) {
                      iox.printStackTrace();
                    }
                    logger.warn(iox);
                    sk.cancel();
                  }
                }

                if (readChannel != null) {
                  try {
                    readMessage(sk, readChannel, incomingAddress);
                  } catch (IOException iox) {
                    // IO exception -> channel closed remotely
                    if (logger.isDebugEnabled()) {
                      iox.printStackTrace();
                    }
                    logger.warn(iox);
                    sk.cancel();
                    readChannel.close();
                    TransportStateEvent e =
                        new TransportStateEvent(
                            DefaultTcpTransportMapping.this,
                            incomingAddress,
                            TransportStateEvent.STATE_DISCONNECTED_REMOTELY,
                            iox);
                    fireConnectionStateChanged(e);
                  }
                }
              }
            }
          } catch (NullPointerException npex) {
            // There seems to happen a NullPointerException within the select()
            npex.printStackTrace();
            logger.warn("NullPointerException within select()?");
          }
          processPending();
        }
        if (ssc != null) {
          ssc.close();
        }
      } catch (IOException iox) {
        logger.error(iox);
        lastError = iox;
      }
      if (!stop) {
        stop = true;
        synchronized (DefaultTcpTransportMapping.this) {
          server = null;
        }
      }
    }
 private void readMessage(SelectionKey sk, SocketChannel readChannel, TcpAddress incomingAddress)
     throws IOException {
   // note that socket has been used
   SocketEntry entry = (SocketEntry) sockets.get(incomingAddress);
   if (entry != null) {
     entry.used();
     ByteBuffer readBuffer = entry.getReadBuffer();
     if (readBuffer != null) {
       readChannel.read(readBuffer);
       if (readBuffer.hasRemaining()) {
         readChannel.register(selector, SelectionKey.OP_READ, entry);
       } else {
         dispatchMessage(incomingAddress, readBuffer, readBuffer.capacity());
       }
       return;
     }
   }
   ByteBuffer byteBuffer = ByteBuffer.wrap(buf);
   byteBuffer.limit(messageLengthDecoder.getMinHeaderLength());
   long bytesRead = readChannel.read(byteBuffer);
   if (logger.isDebugEnabled()) {
     logger.debug("Reading header " + bytesRead + " bytes from " + incomingAddress);
   }
   MessageLength messageLength = new MessageLength(0, Integer.MIN_VALUE);
   if (bytesRead == messageLengthDecoder.getMinHeaderLength()) {
     messageLength = messageLengthDecoder.getMessageLength(ByteBuffer.wrap(buf));
     if (logger.isDebugEnabled()) {
       logger.debug("Message length is " + messageLength);
     }
     if ((messageLength.getMessageLength() > getMaxInboundMessageSize())
         || (messageLength.getMessageLength() <= 0)) {
       logger.error(
           "Received message length "
               + messageLength
               + " is greater than inboundBufferSize "
               + getMaxInboundMessageSize());
       synchronized (entry) {
         entry.getSocket().close();
         logger.info("Socket to " + entry.getPeerAddress() + " closed due to an error");
       }
     } else {
       byteBuffer.limit(messageLength.getMessageLength());
       bytesRead += readChannel.read(byteBuffer);
       if (bytesRead == messageLength.getMessageLength()) {
         dispatchMessage(incomingAddress, byteBuffer, bytesRead);
       } else {
         byte[] message = new byte[byteBuffer.limit()];
         byteBuffer.flip();
         byteBuffer.get(message, 0, byteBuffer.limit() - byteBuffer.remaining());
         entry.setReadBuffer(ByteBuffer.wrap(message));
       }
       readChannel.register(selector, SelectionKey.OP_READ, entry);
     }
   } else if (bytesRead < 0) {
     logger.debug("Socket closed remotely");
     sk.cancel();
     readChannel.close();
     TransportStateEvent e =
         new TransportStateEvent(
             DefaultTcpTransportMapping.this,
             incomingAddress,
             TransportStateEvent.STATE_DISCONNECTED_REMOTELY,
             null);
     fireConnectionStateChanged(e);
   }
 }