NIO。 2个客户端绑定到同一个端口,只能读取1个

时间:2013-02-07 14:18:34

标签: java nio

我有2个客户端套接字绑定在同一端口上侦听。

Selector readSelector = Selector.open();
DeviceUDPReader reader = new DeviceUDPReader();
reader.start();      

//The following is called for each of my 2 servers
void openDevice(String hostName, int hostPort, DriverHandler driverHandler) {
  socketAddress = new InetSocketAddress(hostName, hostPort);    
  writeSelector = Selector.open();
  channel = DatagramChannel.open();
  channel.configureBlocking(false);
  channel.socket().setReuseAddress(true);//Wonderful!! Many servers can respond to same port
  channel.socket().bind(new InetSocketAddress(localPort));// Controller sends data here
  channel.connect(socketAddress);
  channel.register(writeSelector, SelectionKey.OP_WRITE);
  registerChannel(channel, driverHandler);
}

//Register the channels with the read selector
void registerChannel(DatagramChannel channel, DriverHandler driverHandler) throws Exception {
  synchronized(pendingChanges) { 
    //Pending changes a linked list keeping track of changes to be made to Selector
    //ChangeRequest is a simple storage object
    pendingChanges.add(new ChangeRequest(channel, ChangeRequest.REGISTER, driverHandler));
  }
  readSelector.wakeup();
}

选择器的run方法如下

class DeviceUDPReader extends Thread {
DriverHandler driverHandler = null;
@Override
public void run() {
  int len;
  byte[] bb = {};
  ByteBuffer buffer = ByteBuffer.allocate(MAX_BYTES_PER_MESSAGE);
  while (true) {
    try {
      // Process any pending changes to selctor
      synchronized (pendingChanges) {
        Iterator<ChangeRequest> changes = pendingChanges.iterator();
        while (changes.hasNext()) {
          ChangeRequest change = (ChangeRequest) changes.next();
          switch (change.type) {
            case ChangeRequest.REGISTER:
              SelectionKey key = change.channel.register(readSelector, SelectionKey.OP_READ);                  
              key.attach(change.driverHandler);
              System.out.println("Registered channel" + change.channel.getRemoteAddress().toString());//both get registered
              break;
          }
        }
        pendingChanges.clear();
      }


      readSelector.select();//Blocks until at least one of the channels are ready
      System.err.println("TOTAL KEYS " + readSelector.keys().size());//==2

      Iterator<SelectionKey> it = readSelector.selectedKeys().iterator();
      System.out.println("Number of selected keys : " + readSelector.selectedKeys().size());//always 1
      while (it.hasNext()) {
        SelectionKey selKey = it.next();
        if (selKey.isValid() && selKey.isReadable()) {
          DatagramChannel sChannel = (DatagramChannel) selKey.channel();
          System.err.println("GOT SOMETHING FOR SELKEY " + sChannel.getRemoteAddress().toString());
          sChannel.receive(buffer);              
          buffer.flip();
          while ((len = buffer.remaining()) > 0) {                
            bb = new byte[len];
            buffer.get(bb, 0, len);
            System.err.println(new String(bb));
            driverHandler = ((DriverHandler)selKey.attachment());
            if (driverHandler != null) {
              driverHandler.readInput(new ByteArrayInputStream(bb, 0, len));
            }
          }
          buffer.clear();
        }
        it.remove();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  } // end while   
}

}

因此每个通道都有自己的写入选择器,并共享一个读取选择器。

我已经使用wireshark进行监控,并且看到数据正确地从服务器A和服务器B发送和接收。我的读取选择器仅从第一个接收消息,直到我完成并说出channelA.close() 。然后立即获取从服务器B发送的数据。

任何想法我做错了什么?

0 个答案:

没有答案