为什么服务器端显示空指针异常(在客户端服务器应用程序中)?

时间:2015-05-20 14:08:29

标签: java file-io client-server outputstream fileoutputstream

在我的客户端服务器应用程序中,客户端发送一些命令,服务器返回结果。现在的问题是客户端尝试使用GET filename命令从服务器下载文件。该程序工作正常,即使它可以正确加载文件,但问题是在服务器端的命令提示符下始终存在空指针异常错误。它在我输入GET命令后立即发生。错误:

Image

当我在服务器端删除fis.close();行时,会出现第二个问题。它显示服务器端的另一个跟踪错误:错误:

enter image description here

这是我正在进行的完整项目:

客户机侧:

    package clientside;

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class ClientSide {

    private static Socket socket;
    private static PrintWriter outputToServer;
    private static BufferedReader inputFromServer;
    private static InputStream is;
    private static FileOutputStream fos;
    private static final int PORT = 8000;
    private static final String SERVER = "85.197.159.45";
    boolean Connected;
    DataInputStream serverInput;

    public static void main(String[] args) throws InterruptedException {
        String server = "localhost";
        int port = PORT;

        if (args.length >= 1) {
            server = args[0];
        }
        if (args.length >= 2) {
            port = Integer.parseInt(args[1]);
        }

        new ClientSide(server, port);
    }

    public ClientSide(String server, int port) {

        try {
            socket = new Socket(server, port);
            serverInput = new DataInputStream(socket.getInputStream());
            outputToServer = new PrintWriter(socket.getOutputStream(), true);
            inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("Client is connected! ");
            Connected = true;
            String line = null;

            Scanner sc = new Scanner(System.in);
            System.out.print("Type command: ");

            while (sc.hasNextLine()) {
                String request = sc.nextLine();

                if (request.startsWith("exit")) {
                    outputToServer.println(request);
                    System.out.println("Application exited!");
                    //outputToServer.flush();
                    break;
                } else if (request.startsWith("pwd")) {
                    outputToServer.println(request);
                    outputToServer.flush();
                } else if (request.startsWith("list")) {
                    outputToServer.println(request);
                    outputToServer.flush();
                } else if (request.startsWith("GET")) {
                    System.out.print("\r\n");
                    outputToServer.println(request);
                    outputToServer.flush();
                }
                while (Connected) {
                    line = inputFromServer.readLine();
                    System.out.println(line);
                    if (line.isEmpty()) {
                        Connected = false;
                        if (inputFromServer.ready()) {
                            System.out.println(inputFromServer.readLine());
                        }
                    }
                    if (line.startsWith("Status 400")) {
                        while (!(line = inputFromServer.readLine()).isEmpty()) {
                            System.out.println(line);
                        }
                        break;
                    }
                    if (request.startsWith("GET")) {
                        File file = new File(request.substring(4));
                        is = socket.getInputStream();
                        fos = new FileOutputStream(file);

                        byte[] buffer = new byte[socket.getReceiveBufferSize()];
                        serverInput = new DataInputStream(socket.getInputStream());
                        //int bytesReceived = 0;
                        byte[] inputByte = new byte[4000];

                        int length;
                        while ((length = serverInput.read(inputByte, 0, inputByte.length)) > 0) {
                            fos.write(inputByte, 0, length);

                        }

                        /*
                         while ((bytesReceived = is.read(buffer)) >=0) {
                         //while ((bytesReceived = is.read(buffer))>=buffer) {
                         fos.write(buffer, 0, bytesReceived);
                         }
                         */
                        request = "";
                        fos.close();
                        is.close();
                    }
                }
                System.out.print("\nType command: ");
                Connected = true;
            }
            outputToServer.close();
            inputFromServer.close();
            socket.close();
        } catch (IOException e) {
            System.err.println(e);
        }

    }
}

服务器端:

        package serverside;

    import java.io.*;
    import java.net.*;
    import java.util.Arrays;

    public class ServerSide {

        private BufferedReader inputFromClient;
        private PrintWriter outputToClient;
        private FileInputStream fis;
        private OutputStream os;
        private static final int PORT = 8000;
        private ServerSocket serverSocket;
        private Socket socket;

        public static void main(String[] args) {
            int port = PORT;
            if (args.length == 1) {
                port = Integer.parseInt(args[0]);
            }
            new ServerSide(port);
        }

        private boolean fileExists(File[] files, String filename) {
            boolean exists = false;
            for (File file : files) {
                if (filename.equals(file.getName())) {
                    exists = true;
                }
            }
            return exists;
        }

        public ServerSide(int port) {
            // create a server socket
            try {
                serverSocket = new ServerSocket(port);
            } catch (IOException ex) {
                System.out.println("Error in server socket creation.");
                System.exit(1);
            }

            while (true) {
                try {

                    socket = serverSocket.accept();
os = socket.getOutputStream();

                    outputToClient = new PrintWriter(socket.getOutputStream());
                    inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                    while (true) {

                        String request = inputFromClient.readLine();

                        if (!request.startsWith("exit") && !request.startsWith("pwd") && !request.startsWith("list") && !request.startsWith("GET")) {
                            outputToClient.println("Wrong request\r\n"
                                    + "\r\n");
                        } else if (request.startsWith("exit")) {
                            break;
                        } else if (request.startsWith("pwd")) {
                            File file = new File(System.getProperty("user.dir"));
                            outputToClient.print("Status OK\r\n"
                                    + "Lines 1\r\n"
                                    + "\r\n"
                                    + "Working dir: " + file.getName() + "\r\n");
                        } else if (request.startsWith("list")) {
                            File file = new File(System.getProperty("user.dir"));
                            File[] files = file.listFiles();
                            outputToClient.print("Status OK\r\n"
                                    + "Files " + files.length + "\r\n"
                                    + "\r\n"
                                    + Arrays.toString(files).substring(1, Arrays.toString(files).length() - 1) + "\r\n");
                        } else if (request.startsWith("GET")) {
                            String filename = request.substring(4);
                            File file = new File(System.getProperty("user.dir"));
                            File[] files = file.listFiles();

                            if (fileExists(files, filename)) {
                                file = new File(filename);
                                int fileSize = (int) file.length();

                                outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n",
                                        fileSize, filename);
                                outputToClient.flush();

                                try (FileInputStream fis = new FileInputStream(file)) {

                                    byte[] buffer = new byte[(1 << 7) - 1];
                                    int bytesRead = 0;

                                    while ((bytesRead = fis.read(buffer)) != -1) {
                                        os.write(buffer, 0, bytesRead);
                                    }

                                }
                                os.close();
                                fis.close();//NPE is happening here.
                            } else {
                                outputToClient.print("Status 400\r\n"
                                        + "File " + filename + " not found\r\n"
                                        + "\r\n");
                                outputToClient.flush();
                            }
                        }
                        outputToClient.flush();
                    }
                } catch (IOException e) {
                    System.err.println(e);
                }

finally{
os.close();
}
            }
        }
    }

更新:即使我从服务器端删除fis.close();行,也会显示java.net.SocketException: socket closed错误。

3 个答案:

答案 0 :(得分:1)

最初的问题是,您正在使用带有指定变量的try-with-resources块,该变量与您的一个类成员变量具有相同的名称。删除以下行将删除NPE:

fis.close();

SocketException由以下行引起:

os.close();

根据Socket::getOutputStream的{​​{3}}:

  

关闭返回的OutputStream将关闭相关的套接字。

因此,将行os = socket.getOutputStream();移至行socket = serverSocket.accept();线的正下方,并在最后os.close()块之后将finally移至catch块应该解决这个问题。

答案 1 :(得分:0)

fis表示的套接字为空。

要更正,请使用:

if (fis != null) fis.close;

答案 2 :(得分:0)

try (FileInputStream fis = new FileInputStream(file)) 在这一行中,您将创建一个新的FileInputStream并使用它,而不是之前声明的FileInputStream字段。此fis仅存在于&#34;尝试&#34;块。当您尝试关闭fis os.close();时,您试图关闭fis字段,而不是fis中声明的try

请改用:

try (fis = new FileInputStream(file))。有了这个,您将在字段中实例化一个新的FileInputStream,而不是在一个新变量中。