0

我正在尝试使用 NIO 来构建一个高效的 Socket TCP/IP 服务器。

我有一个接受连接的主线程,然后将其添加到另一个线程,该线程应该等待来自客户端的消息然后读取它。

当我对所有操作只使用一个线程和一个选择器时,它工作得很好,但是当我试图让它与 2 个线程和 2 个选择器一起工作时,传入的连接接受正在工作,但读取不是,我认为它因为我的选择器阻塞了线程,因此他不知道我已经注册了一个新的 SocketChannel。

这是我的主线程:

public static void main(String[] args) {
   try {
      System.out.println("Who's Around Server Started!");
      Selector connectionsSelector = null;
      ServerSocketChannel server = null;
      String host = "localhost";
      int port = 80;    
      LiveConnectionsManager liveConnectionsManager =
         new LiveConnectionsManager();
      liveConnectionsManager.start();
      connectionsSelector = Selector.open();
      server = ServerSocketChannel.open();
      server.socket().bind(new InetSocketAddress(host,port));
      server.configureBlocking(false);
      server.register(connectionsSelector, SelectionKey.OP_ACCEPT);
      while (true) {
         connectionsSelector.select();
         Iterator<SelectionKey> iterator =
            connectionsSelector.selectedKeys().iterator();
         while (iterator.hasNext()) {
            SelectionKey incomingConnection = iterator.next();
            iterator.remove();
            if( incomingConnection.isConnectable()) {
               ((SocketChannel)incomingConnection.channel()).finishConnect();
            }
            if( incomingConnection.isAcceptable()){
               acceptConnection(server.accept(), liveConnectionsManager);
            }
         }
      }
   } catch (Throwable e) {
      throw new RuntimeException("Server failure: " + e.getMessage());
   } 
}

private static void acceptConnection(
   SocketChannel acceptedConnection,
   LiveConnectionsManager liveConnectionsManager ) throws IOException
{
   acceptedConnection.configureBlocking(false);
   acceptedConnection.socket().setTcpNoDelay(true);
   System.out.println(
      "New connection from: " + acceptedConnection.socket().getInetAddress());
   liveConnectionsManager.addLiveConnection(acceptedConnection);
}

这是我的 LiveConnectionsManager:

private Selector messagesSelector;

public LiveConnectionsManager(){
   try {
      messagesSelector = Selector.open();           
   } catch (IOException e) {
      System.out.println("Couldn't run LiveConnectionsManager");
   }
}


@Override
public void run() {
   try {
      System.out.println("LiveConnectionManager Started!");
      while(true) {             
         messagesSelector.select();
         Iterator<SelectionKey> iterator = messagesSelector.keys().iterator();
         while (iterator.hasNext()){
            SelectionKey newData = iterator.next();
            iterator.remove();
            if( newData.isReadable()){
               readIncomingData(((SocketChannel)newData.channel()));
            }
         }
      }
   } catch (IOException e) {
      e.printStackTrace();
   }
}

public void addLiveConnection( SocketChannel socketChannel )
   throws ClosedChannelException
{
   socketChannel.register(messagesSelector, SelectionKey.OP_READ);      
}
4

0 回答 0