java - 如何使用NIO套接字只写入一次或 "on some command"?

标签 java sockets nio

这是我在阅读的书中找到的 chargen 服务器的示例:

import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;

public class ChargenServer {

  public static int DEFAULT_PORT = 19;

  public static void main(String[] args) {

    int port;
    try {
      port = Integer.parseInt(args[0]);
    }
    catch (Exception ex) {
      port = DEFAULT_PORT;
    }
    System.out.println("Listening for connections on port " + port);

    byte[] rotation = new byte[95*2];
    for (byte i = ' '; i <= '~'; i++) {
        rotation[i-' '] = i;
        rotation[i+95-' '] = i;
    }

    ServerSocketChannel serverChannel;
    Selector selector;
    try {
      serverChannel = ServerSocketChannel.open();
      ServerSocket ss = serverChannel.socket();
      InetSocketAddress address = new InetSocketAddress(port);
      ss.bind(address);
      serverChannel.configureBlocking(false);
      selector = Selector.open();
      serverChannel.register(selector, SelectionKey.OP_ACCEPT);
    }
    catch (IOException ex) {
      ex.printStackTrace();
      return;
    }

    while (true) {

      try {
        selector.select();
      }
      catch (IOException ex) {
        ex.printStackTrace();
        break;
      }

      Set readyKeys = selector.selectedKeys();
      Iterator iterator = readyKeys.iterator();
      while (iterator.hasNext()) {

        SelectionKey key = (SelectionKey) iterator.next();
        iterator.remove();
        try {
          if (key.isAcceptable()) {
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel client = server.accept();
            System.out.println("Accepted connection from " + client);
            client.configureBlocking(false);
            SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE);
            ByteBuffer buffer = ByteBuffer.allocate(74);
            buffer.put(rotation, 0, 72);
            buffer.put((byte) '\r');
            buffer.put((byte) '\n');
            buffer.flip();
            key2.attach(buffer);
          }
          else if (key.isWritable()) {
            SocketChannel client = (SocketChannel) key.channel();
            ByteBuffer buffer = (ByteBuffer) key.attachment();
            if (!buffer.hasRemaining()) {
              // Refill the buffer with the next line
              buffer.rewind();
              // Get the old first character
              int first = buffer.get();
              // Get ready to change the data in the buffer
              buffer.rewind();
              // Find the new first characters position in rotation
              int position = first - ' ' + 1;
              // copy the data from rotation into the buffer
              buffer.put(rotation, position, 72);
              // Store a line break at the end of the buffer
              buffer.put((byte) '\r');
              buffer.put((byte) '\n');
              // Prepare the buffer for writing
              buffer.flip();
            }
            client.write(buffer);
          }
        }
        catch (IOException ex) {
          key.cancel();
          try {
            key.channel().close();
          }
          catch (IOException cex) {}
        }

      }

    }

  }

}

一旦客户端连接到服务器,它就会不断向客户端发送字符流并且不会停止。

我很好奇我是否想发送一次缓冲区并仍然保持服务器与客户端的连接。我该怎么办?

最佳答案

套接字 channel 几乎总是可写的。仅当您之前进行过零长度写入时,才应选择 OP_WRITE。如果你有东西要写,就写它,然后检查返回值。

关于java - 如何使用NIO套接字只写入一次或 "on some command"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42055408/

相关文章:

java - 如何正确使用NIO选择器?

java - 为什么我应该在写入数据之前检查 channel isWritable()

java - Wicket 中是否有 Activity 指示器?

java - 在测试中断言 java.util.Date 字段

java - 从 Wrapper 到原始类型以及从原始类型到 Wrapper 的空间高效转换

C 套接字 : using shutdown() to stop server running in background

java - java中nio和协程是什么关系?

java - 如何根据这段代码中的某些条件来显示图像和不同的变量?

java - 直接从 Java 中的模型类创建 JSON 对象

sockets - 使用 J2ME 进行套接字编程