尝试从InputStream重复读取时发生空指针异常

时间:2014-02-23 06:30:51

标签: java sockets

当我在发送一条指令后关闭客户端时,代码工作正常。但是当我希望客户端和服务器连接保持不变时,客户端可以一个接一个地向服务器发送多个指令,我在服务器上得到一个Null指针异常,在客户端得到消息java.net.SocketException: Socket is closed。这在客户端将文件发送到服务器并且服务器成功接收到它之后发生。需要帮忙。错误发生在连接类代码行switch(clientMsg)。在我看来,由于某种原因BufferedReader innull,但我可能会对此感到错误。代码如下。感谢。

服务器

public class server {
private static ServerSocket serverSocket;
private static Socket socket = null;

public static void print(Object s) {
    System.out.println(s);
}


@SuppressWarnings("resource")
public static void main (String args[]) throws IOException {
    System.out.print("Specify listening port: ");
    Scanner _a = new Scanner(System.in);
    int a = _a.nextInt();
    try{
        serverSocket = new ServerSocket(a);
    }
    catch(IOException e) {
        System.out.println(e);
    }

    while (true) {
        try {
            socket = serverSocket.accept();
            print("Connected to " + socket);

            Thread client = new Thread(new Connection(socket));
            client.start();
        }
        catch (IOException e) {
            print(e);
        }
    }

}

}

连接

public class Connection implements Runnable {

public static void print(Object s) {
    System.out.println(s);
}

private Socket socket;
private BufferedReader in = null;

public Connection(Socket client) {
    this.socket = client;
}

@Override
public void run(){
    try {
        in = new BufferedReader(new InputStreamReader(
                socket.getInputStream()));

        String clientMsg;
        while (true) {
            clientMsg = in.readLine();
            switch (clientMsg) {
            case "1":
                receiveFile(); //method code not included
                break;

            default:
                print("Command not recognized");
                break;
            }
            //in.close();
        }

    }//try run()
    catch (IOException e) {
        print(e);
    }
}

客户

public class client {
private static Socket connectToServer;
private static String fileName;
private static BufferedReader keybrdIn;
private static PrintStream msgToServer;

public static void println(Object e) {
    System.out.println(e);
}

public static void print(Object e) {
    System.out.print(e);
}

public static void main(String args[]) throws IOException{
    try{
        print("Enter IP: ");
        String ip = new Scanner(System.in).nextLine();          
        print("Enter port: ");
        int port = new Scanner(System.in).nextInt();
        connectToServer = new Socket(ip, port);
        keybrdIn = new BufferedReader(new InputStreamReader(System.in));
    }catch(IOException e) {
        println(e);
    }

    msgToServer = new PrintStream(connectToServer.getOutputStream());

    while (true) {
        try {
            switch(Integer.parseInt(action())) { //action() method code not included
            case 1:
                msgToServer.println("1");
                sendFile();
                break;
            default:
                println("Invalid input");
                break;
            }
        }catch (IOException e) {
            println(e);
        }
    }
}

的sendfile()

public static void sendFile() throws IOException {
    print("Enter file name: ");
    fileName = keybrdIn.readLine();

    File file = new File(fileName);

    byte[] bytearray = new byte[8192];
    FileInputStream fis = new FileInputStream(file);
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    OutputStream os = connectToServer.getOutputStream();
    DataOutputStream dos = new DataOutputStream(os);
    dos.writeUTF(file.getName());
    int count;
    while ((count = dis.read(bytearray)) > 0){
        dos.write(bytearray, 0, count);
    }
    dis.close();
    dos.flush();
    dos.close();
}

receiveFile()

public void receiveFile() {
    try {
        int count;

        DataInputStream clientFileStream = new DataInputStream(socket.getInputStream());

        String fileName = clientFileStream.readUTF();
        OutputStream fileOutput = new FileOutputStream("_" + fileName);

        byte[] mybytearray = new byte[8192];
        BufferedOutputStream bos = new BufferedOutputStream(fileOutput);

        System.out.println("Downloading " + fileName + " ...");
        //outToClient().writeBytes("Uploading. Please wait...\n");
        while ((count = clientFileStream.read(mybytearray)) > 0){
            bos.write(mybytearray, 0, count);
        }
        fileOutput.close();
        bos.close();
        clientFileStream.close();

    }
    catch (IOException e) {
        print(e);
    }
}

3 个答案:

答案 0 :(得分:1)

在sendFile()中,关闭数据输出流,关闭底层连接的输出流。

根据Socket.getOutputStream()的文档:

  

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

答案 1 :(得分:1)

由于您已经关闭了流,它也将关闭套接字以及Eyal提到的。但是,在关闭流时,服务器端将知道这一点并返回-1以获取read()结果。 因此,即使您没有在开始时指定文件长度,这通常也能正常工作。

但是,由于您已经关闭了流,因此无论如何都无法重用它。要解决此问题,可能需要更改Client类,以便Client应创建套接字连接,发送文件,关闭套接字。这是打开的客户端套接字的一个生命周期。

或者也许在Client类的while循环中,1)取ip,port和filename发送2)创建新的Thread并提供这些信息让线程打开连接,发送文件,关闭连接3)同时, client while()可以保持从用户发送下一个ip,port和filename。通过这样做,您无需使客户端程序等待文件传输完成。

答案 2 :(得分:0)

关于服务器中的NPE,readLine()在流结束时返回null。你忽略了它。你应该在调用之后立即测试它,如果null关闭套接字并退出读循环。