Java: SocketChannel.read() работает только один раз за выполнение программы на FTP-сервере

Мне было предложено выполнить это упражнение с просьбой создать простой FTP-сервер, где клиент запрашивает файл по имени файла с помощью SocketChannel, сервер получает имя файла, открывает файловый канал для чтения файла и отправляет его клиенту. селектором.

Вот что я придумал: это сервер

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

public class MainClassServer
{
    public static final int BUFFER_DIM = 64;
    public static int DEFAULT_PORT = 1919;

    public static void main(String[] args)
    {
        int port;
        try
        {
            port = Integer.parseInt(args[0]);
        }
        catch (RuntimeException 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 <SelectionKey> readyKeys = selector.selectedKeys();
            Iterator <SelectionKey> iterator = readyKeys.iterator();

            while (iterator.hasNext())
            {
                SelectionKey key = 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 filenameBuffer = ByteBuffer.allocate(256);
                        int nRead = client.read(filenameBuffer);
                        System.out.println("readed " + nRead);
                        filenameBuffer.flip();

                        String filenameString = new String(filenameBuffer.array()).trim();
                        System.out.println("filename is: " + filenameString);

                        FileChannel writeChannel = FileChannel.open(Paths.get(filenameString));

                        key2.attach(writeChannel);
                    }
                    else if (key.isWritable())
                    {
                        SocketChannel client = (SocketChannel)key.channel();
                        FileChannel fileChannel = (FileChannel)key.attachment();

                        ByteBuffer bytesRead = ByteBuffer.allocate(BUFFER_DIM);
                        int nRead = fileChannel.read(bytesRead);
                        System.out.println("i readed from the file channel some " + nRead);

                        if(nRead >= 0)
                        {
                            bytesRead.flip();
                            client.write(bytesRead);
                        }
                        else
                        {
                            fileChannel.close();
                            client.close();
                        }
                    }
                }
                catch (IOException ex)
                {
                    key.cancel();
                    try
                    {
                        key.channel().close();
                    }
                    catch (IOException cex) {}
                }
            }
        }
    }
}

И это клиент:

import java.nio.*;
import java.nio.channels.*;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.net.*;
import java.io.IOException;
public class MainClassClient
{
    public static int DEFAULT_PORT = 1919;
    public static void main(String[] args)
    {
        if (args.length == 0)
        {
            System.out.println("Usage: java IntgenClient host [port]");
            return;
        }

        int port;
        try
        {
            port = Integer.parseInt(args[0]);
        }
        catch (RuntimeException ex)
        {
            port = DEFAULT_PORT;
        }
        try
        {
            SocketAddress address = new InetSocketAddress("127.0.0.1", port);
            SocketChannel client = SocketChannel.open(address);

            ByteBuffer filenameBuffer = ByteBuffer.allocate(args[1].length());
            filenameBuffer.put(args[1].getBytes());
            filenameBuffer.flip();
            System.out.println("i wrote " + client.write(filenameBuffer));

            ByteBuffer readBuffer = ByteBuffer.allocateDirect(1024*1024);

            FileChannel downloadChannel = FileChannel.open(Paths.get("downloaded" + args[1]),
                    StandardOpenOption.CREATE, StandardOpenOption.WRITE);

            while(client.read(readBuffer) != -1)
            {
                readBuffer.flip();
                downloadChannel.write(readBuffer);
                while(readBuffer.hasRemaining())
                {
                    System.out.print((char)readBuffer.get());
                }
                readBuffer.clear();
            }

            downloadChannel.close();
            client.close();
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
    }
}

Он отлично работает и загружает файлы, которые я ему передаю, но проблема в том, что он работает только один раз за каждое выполнение сервера. Если я снова запускаю клиент и спрашиваю тот же файл с сервером, который все еще открыт, то это то, что сервер дает мне.

Listening for connections on port 1919
Accepted connection from java.nio.channels.SocketChannel[connected local=/127.0.0.1:1919 remote=/127.0.0.1:49198]
Exception in thread "main" java.lang.NullPointerException
    at MainClassServer.main(MainClassServer.java:105)
readed 0
filename is: 

Ряд 105

int nRead = fileChannel.read(bytesRead);

Но вывод говорит мне, что SocketChannel.read() сделано при регистрации ключа.

Я довольно новичок в селекторах и ненавижу их. Так что я делаю не так?

0 ответов

Другие вопросы по тегам