コード例 #1
0
 private void recv(SocketChannel sc, ClientInfo ci) throws IOException {
   ci.channel.read(ci.inBuf);
   ByteBuffer tmpBuf = ci.inBuf.duplicate();
   tmpBuf.flip();
   int bytesProcessed = 0;
   boolean doneLoop = false;
   while (!doneLoop) {
     byte b;
     try {
       b = tmpBuf.get();
     } catch (BufferUnderflowException bue) {
       // Processed all data in buffer
       ci.inBuf.clear();
       doneLoop = true;
       break;
     }
     switch (b) {
       case TypeServerConstants.WELCOME:
         bytesProcessed++;
         break;
       case TypeServerConstants.GET_STRING_REQUEST:
         bytesProcessed++;
         if (ci.outputPending) {
           // Client is backed up. We can't append to
           // the byte buffer because it's in the wrong
           // state. We could allocate another buffer
           // here and change our send method to know
           // about multiple buffers, but we'll just
           // assume that the client is dead
           break;
         }
         ci.outBuf.put(TypeServerConstants.GET_STRING_RESPONSE);
         ByteBuffer strBuf = encoder.encode(testString);
         ci.outBuf.putShort((short) strBuf.remaining());
         ci.outBuf.put(strBuf);
         ci.outBuf.flip();
         send(sc, ci);
         break;
       case TypeServerConstants.GET_STRING_RESPONSE:
         int startPos = tmpBuf.position();
         try {
           int nBytes = tmpBuf.getInt();
           byte[] buf = new byte[nBytes];
           tmpBuf.get(buf);
           bytesProcessed += buf.length + 5;
           String s = new String(buf);
           // Send the string to the GUI
           break;
         } catch (BufferUnderflowException bue) {
           // Processed all available data
           ci.inBuf.position(ci.inBuf.position() + bytesProcessed);
           doneLoop = true;
         }
         break;
     }
   }
 }
コード例 #2
0
// 感觉如果没有看过 NIO 的详细内容是不会懂这部分
public class TypeServer extends TCPNIOServer {
  static String testString = "Thisisateststring";

  static class ClientInfo {
    ByteBuffer inBuf = ByteBuffer.allocateDirect(512);
    ByteBuffer outBuf = ByteBuffer.allocateDirect(512);
    boolean outputPending = false;
    SocketChannel channel;
  }

  Map allClients = new HashMap();
  Charset encoder = Charset.forName("UTF-8");

  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);
  }

  private void recv(SocketChannel sc, ClientInfo ci) throws IOException {
    ci.channel.read(ci.inBuf);
    ByteBuffer tmpBuf = ci.inBuf.duplicate();
    tmpBuf.flip();
    int bytesProcessed = 0;
    boolean doneLoop = false;
    while (!doneLoop) {
      byte b;
      try {
        b = tmpBuf.get();
      } catch (BufferUnderflowException bue) {
        // Processed all data in buffer
        ci.inBuf.clear();
        doneLoop = true;
        break;
      }
      switch (b) {
        case TypeServerConstants.WELCOME:
          bytesProcessed++;
          break;
        case TypeServerConstants.GET_STRING_REQUEST:
          bytesProcessed++;
          if (ci.outputPending) {
            // Client is backed up. We can't append to
            // the byte buffer because it's in the wrong
            // state. We could allocate another buffer
            // here and change our send method to know
            // about multiple buffers, but we'll just
            // assume that the client is dead
            break;
          }
          ci.outBuf.put(TypeServerConstants.GET_STRING_RESPONSE);
          ByteBuffer strBuf = encoder.encode(testString);
          ci.outBuf.putShort((short) strBuf.remaining());
          ci.outBuf.put(strBuf);
          ci.outBuf.flip();
          send(sc, ci);
          break;
        case TypeServerConstants.GET_STRING_RESPONSE:
          int startPos = tmpBuf.position();
          try {
            int nBytes = tmpBuf.getInt();
            byte[] buf = new byte[nBytes];
            tmpBuf.get(buf);
            bytesProcessed += buf.length + 5;
            String s = new String(buf);
            // Send the string to the GUI
            break;
          } catch (BufferUnderflowException bue) {
            // Processed all available data
            ci.inBuf.position(ci.inBuf.position() + bytesProcessed);
            doneLoop = true;
          }
          break;
      }
    }
  }

  private void send(SocketChannel sc, ClientInfo ci) throws IOException {
    int len = ci.outBuf.remaining();
    int nBytes = sc.write(ci.outBuf);
    if (nBytes != len) {
      // Client not ready to receive data
      ci.outputPending = true;
      ci.channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
    } else {
      ci.outBuf.clear();
      if (ci.outputPending) {
        ci.outputPending = false;
        ci.channel.register(selector, SelectionKey.OP_READ);
      }
    }
  }

  protected void registeredClient(SocketChannel sc) throws IOException {
    ClientInfo ci = new ClientInfo();
    ci.channel = sc;
    ci.outBuf.clear();
    ci.outBuf.put(TypeServerConstants.WELCOME);
    ci.outBuf.flip();
    allClients.put(sc, ci);
    send(sc, ci);
  }

  public static void main(String[] args) throws Exception {
    TypeServer ts = new TypeServer();
    ts.port = Integer.parseInt(args[0]);
    Thread t = new Thread(ts);
    t.start();
    System.out.println("Type server ready...Type CTRL-D to exit");
    while (System.in.read() > 0) ;
    ts.stopServer();
    t.join();
  }
}