java.lang.NullPointerException和java.net.SocketException

时间:2013-10-01 20:04:38

标签: java sockets exception pointers null

我正在尝试使用Java套接字程序。在这里,客户端发送一个字符串,该字符串应由服务器反转并发送回客户端。服务器是多线程服务器。这是客户端代码:

import java.io.*;
import java.net.*;

class ClientSystem
{
    public static void main(String[] args)
    {
            String hostname = "127.0.0.1";
            int port = 1234;

            Socket clientsocket = null;
            DataOutputStream output =null;
            BufferedReader input = null;

            try
            {
                    clientsocket = new Socket(hostname,port);
                    output = new DataOutputStream(clientsocket.getOutputStream());
                    input = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
            }
            catch(Exception e)
            {
                    System.out.println("Error occured"+e);
            }

            try
            {
                    while(true)
                    {
                            System.out.println("Enter input string ('exit' to terminate connection): ");
                            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                            String inputstring = br.readLine();
                            output.writeBytes(inputstring+"\n");

                            //int n = Integer.parseInt(inputstring);
                            if(inputstring.equals("exit"))
                                    break;

                            String response = input.readLine();
                            System.out.println("Reversed string is: "+response);

                            output.close();
                            input.close();
                            clientsocket.close();
                    }
            }
            catch(Exception e)
            {
                    System.out.println("Error occured."+e);
            }
    }
}

这是服务器端代码:

import java.io.*;
import java.net.*;

public class ServerSystem
{
    ServerSocket server = null;
    Socket clientsocket = null;
    int numOfConnections = 0, port;

    public ServerSystem(int port)
    {
            this.port = port;
    }

    public static void main(String[] args)
    {
            int port = 1234;
            ServerSystem ss = new ServerSystem(port);
            ss.startServer();
    }

    public void startServer()
    {
            try
            {
                    server = new ServerSocket(port);
            }
            catch(Exception e)
            {
                    System.out.println("Error occured."+e);
            }

            System.out.println("Server has started. Ready to accept connections.");

            while(true)
            {
                    try
                    {
                            clientsocket = server.accept();
                            numOfConnections++;
                            ServerConnection sc = new ServerConnection(clientsocket, numOfConnections, this);
                            new Thread(sc).start();
                    }
                    catch(Exception e)
                    {
                            System.out.println("Error occured."+e);
                    }
            }
    }

    public void stopServer()
    {
            System.out.println("Terminating connection");
            System.exit(0);
    }
}

class ServerConnection extends Thread
{
    BufferedReader br;
    PrintStream ps;
    Socket clientsocket;
    int id;
    ServerSystem ss;

    public ServerConnection(Socket clientsocket, int numOfConnections, ServerSystem ss)
    {
            this.clientsocket = clientsocket;
            id = numOfConnections;
            this.ss = ss;

            System.out.println("Connection "+id+" established with "+clientsocket);
            try
            {
                    br = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
                    ps = new PrintStream(clientsocket.getOutputStream());
            }
            catch(Exception e)
            {
                    System.out.println("Error occured."+e);
            }
    }

    public void run()
    {
            String line, reversedstring = "";

            try
            {
                    boolean stopserver = false;
                    while(true)
                    {
                            line = br.readLine();
                            System.out.println("Received string: "+line+" from connection "+id);
                            //long n = Long.parseLong(line.trim());

                            if(line.equals("exit"))
                            {
                                    stopserver = true;
                                    break;
                            }
                            else
                            {
                                    int len = line.length();
                                    for (int i=len-1; i>=0; i--)
                                            reversedstring = reversedstring + line.charAt(i);
                                            ps.println(""+reversedstring);
                            }
                    }
                    System.out.println("Connection "+id+" is closed.");
                  br.close();
                    ps.close();
                    clientsocket.close();

                    if(stopserver)
                            ss.stopServer();
            }
            catch(Exception e)
            {
                    System.out.println("Error occured."+e);
            }
    }
}

当我输入字符串时,我在服务器端代码上遇到java.lang.NullPointerException,当我尝试重新输入字符串时,我得到一个java.net.SocketException:Socket关闭异常。

客户端输出:

Enter input string ('exit' to terminate connection): 
usa
Reversed string is: asu
Enter input string ('exit' to terminate connection): 
usa
Error occured.java.net.SocketException: Socket closed

服务器端输出:

Server has started. Ready to accept connections.
Connection 1 established with Socket[addr=/127.0.0.1,port=3272,localport=1234]
Received string: usa from connection 1
Received string: null from connection 1
Error occured.java.lang.NullPointerException

我尝试了很多但是我没有得到这些例外的地方。有人可以帮我从这里出去吗?先感谢您! :)

3 个答案:

答案 0 :(得分:1)

这3行是客户端代码中的罪魁祸首:

output.close();
input.close();
clientsocket.close();

将它们放在while循环之外,并在finally块中:

try {
    while(true) {
      // client code here
    }
} catch (Exception e) {
     e.printStackTrace(); //  notice this line. Will save you a lot of time!
} finally {
    output.close(); //close resources here!
    input.close();
    clientsocket.close();
}

问题是,就像它最初一样,你关闭了所有资源,但在下一次迭代中,你想要使用它们,而不是初始化它们......

旁注

正确处理异常,包括正确记录异常。始终使用log4j

等日志框架
LOG.error("Unexpected error when deionizing the flux capacitor",e);

printStackTrace()方法

e.printStackTrace();

如果您发布了堆栈跟踪,请不要忘记在代码中包含行号。

修改

对于相反的问题:

else
{
    int len = line.length();

    reversedString=""; //this line erases the previous content of the reversed string

    for (int i=len-1; i>=0; i--) { //always use brackets!!!
        reversedstring = reversedstring + line.charAt(i);
    }
    ps.println(""+reversedstring);
}

发生什么事了? reversString只是随着每次迭代而增长和增长,而不会被删除...这就是为什么我喜欢在我需要的最严格的范围内声明我的变量。

修改

要使退出命令不对服务器执行,这可以是一个(非常简单)的解决方案:

在ServerConnection类中:

while(true)
{
    line = br.readLine();
    System.out.println("Received string: "+line+" from connection "+id);

    if(line.equals("exit"))
    {
        break; //just stop this connection, don't kill server
    }
    else if(line.equals("stop"))
    {
        stopserver = true; //stop server too
        break;
    }
    else
    {
        int len = line.length();
        for (int i=len-1; i>=0; i--) {
            reversedstring = reversedstring + line.charAt(i);
        }
        ps.println(""+reversedstring);
    }
}

这里发生了什么?有一个新的“命令”stop,它使服务器停止,退出只是退出客户端,但不会停止服务器本身......

答案 1 :(得分:0)

在循环的第一次运行中,您将关闭导致问题的所有连接。                             output.close();                             input.close();                             clientsocket.close();,将其向下移动

答案 2 :(得分:0)

您的服务器正在调用br.readLine();它会等到客户端发送它,但是一旦发送了一个字符串,您就会调用:

  output.close();
  input.close();
  clientsocket.close();

这将释放资源并导致br.readLine()成为null

if (line.equals("exit")) {此行为空,因此您无法调用等号。

if ("exit".equals(line)) {您可以像这样更改它以防止此异常。

将close语句移动到finally块,即使在服务器中也是如此,如果你在while中有异常,则永远不会达到关闭,这可能会导致内存泄漏。

客户端:

} finally {
  output.close();
  input.close();
  clientsocket.close();
}

服务器:

} finally {
  br.close();
  ps.close();
  clientsocket.close();
}

注意:您可以在关闭之前验证它们,以确保它们不为空。

你可能必须提供输入为null的情况,或者退出循环,通常你会使用这样的东西: if (null==line || "exit".equals(line)) {

如果客户端发送null,则表示出错。