【问题标题】:send file using java NIO selector使用 java NIO 选择器发送文件
【发布时间】:2015-02-05 11:52:27
【问题描述】:

我正在尝试使用 java NIO 选择器键从服务器发送文件,但是当我关闭服务器时,我从客户端收到了整个文件。

服务器端代码

    public static int DEFAULT_PORT = 1234;

public static void main(String[] args) {
    String fileName = "10mb.txt";
    int port;

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

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

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

                    String filePath = (fileName);
                    File file = new File(filePath);
                    int fileSize = (int) file.length();
                    System.out.println("File size =" + fileSize);
                    FileInputStream fis;
                    ByteBuffer buffer = null;

                    try {
                        fis = new FileInputStream(file);
                        FileChannel fc = fis.getChannel();
                        buffer = ByteBuffer.allocate(fileSize);
                        try {
                            fc.read(buffer);
                        } catch (IOException ex) {
                            System.out.println("IO EX :" + ex);
                        }
                    } catch (FileNotFoundException ex) {
                        System.out.println("FileNotFoundEx :" + ex);
                    }

                    buffer.flip();
                    key2.attach(buffer);

                } else if (key.isWritable()) {

                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer out = (ByteBuffer) key.attachment();

                    client.write(out);
                }

            } catch (IOException ex) {
                System.out.println("IO Exeption :" + ex);
                key.cancel();
                try {
                    key.channel().close();
                } catch (IOException cex) {
                    System.out.println(cex);
                }
            }
            iterator.remove();

        }

    }

}

客户端代码

public static void main(String[] args) throws IOException {
    String fileName = "10mb.txt";
    int bufferSize = 2048;
    int n = 0;
    int read = 0;

    SocketChannel socket = SocketChannel.open(new InetSocketAddress(1234));
    String filePath = (fileName);

    FileOutputStream out = new FileOutputStream(filePath);
    FileChannel file = out.getChannel();
    ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

    long startTime = System.currentTimeMillis();


    while ((read = socket.read(buffer)) > 0) {
        buffer.flip();

        file.write(buffer);

        n = n + read;

        buffer.clear();

        System.out.println(n);
    }
    long endTime = System.currentTimeMillis();
    long difference = endTime - startTime;
    System.out.println("File with " + n + " bytes downloaded in " + difference + " ms");
    socket.close();

    file.close();

    out.close();
}

感谢您的帮助。

【问题讨论】:

    标签: java file client nio server


    【解决方案1】:

    您假设fc.read() 填充了缓冲区,而sc.write() 将其清空。这两个假设都不成立。 Java中通道间复制的正确方法如下:

    while (in.read(buffer) > 0 || buffer.position() > 0)
    {
        buffer.flip();
        out.write(buffer);
        buffer.compact();
    }
    

    当您在非阻塞模式下输出到SocketChannel 时,您需要针对write() 返回零的情况进行修改:如果发生这种情况,您需要为 OP_WRITE 注册通道,返回到select() 循环,并在OP_WRITE 触发时恢复此循环:这一次,如果write() 返回非零,则注销OP_WRITE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多