Java Socket I/O 流空指针异常

标签 java sockets

我编写了一个简单的客户端和服务器来自学一些网络知识。它的设置方式是我有一个主服务器类,它将处理创建/销毁套接字,以及代表每个连接的 ConnectionThread 类(每个连接都有自己的线程)。客户端非常简单。

问题在于在 ConnectionThread 类中创建输入/输出流。我不确定问题到底是什么,但是当简单的测试客户端尝试连接时它崩溃了,给我这个:

~~MMO Server Alpha .1~~
Constructed Server
Server Initialized, preparing to start...
Server preparing to check if it should be listening...
Server should be listening, continuing as planned.
ServerSocket passed to ConnectionThread: ServerSocket[addr=0.0.0.0/0.0.0.0,localport=6969]
Constructing ConnectionThread.
Socket[addr=/10.0.1.10,port=55332,localport=6969]
ConnectionThread constructed.
Exception in thread "main" java.lang.NullPointerException
    at ConnectionThread.init(ConnectionThread.java:65)
    at Server.listen(Server.java:98)
    at Server.start(Server.java:62)
    at Server.main(Server.java:122)
ConnectionThread added to queue.
Establishing in and out streams:
null

以下是类(为简洁起见进行了修改):

public class Server {
    int PORT;
    boolean shouldListen;
    ArrayList<ConnectionThread> connections = new ArrayList<ConnectionThread>();
    ServerSocket serverSocket;



    public Server() {

        try {
            PORT = 6969;
            shouldListen = true;
            serverSocket = new ServerSocket(PORT);
        }
        catch (IOException e) {

            System.out.println("Error in server constructor.");
            System.exit(1);
        }
    }



    public void start() {
        System.out.println("Server preparing to check if it should be listening...");
        listen();
        System.out.println("Server finished listening.");
    }


    public void listen() {
        while (shouldListen) {
            ConnectionThread conn = null;
            System.out.println("Server should be listening, continuing as planned.");
            try {
            conn = new ConnectionThread(serverSocket);
            }
            catch (Exception e) {
                System.out.println("____Error constructing ConnectionThread. Could there be another instance of the server running?");
                System.exit(1);
            }
            System.out.println("ConnectionThread constructed.");

            connections.add(conn);
            System.out.println("ConnectionThread added to queue.");

            conn.init();
            System.out.println("Finished ConnectionThread initialization, verifying...");

            if (conn.isInitialized) {
                System.out.println("ConnectionThread Initialized, preparing to start new thread.");
                (new Thread(conn)).start();
            }
        }
    }


    public static void main(String[] args) {
        System.out.println("~~MMO Server Alpha .1~~");
        Server server = new Server();
        System.out.println("Constructed Server");
        server.init();
        System.out.println("Server Initialized, preparing to start...");
        server.start();

    }

}

这是 ConnectionThread 类:

public class ConnectionThread implements Runnable {
    boolean shouldBeListening = true;
    boolean isThereAnUnsentOutgoingMessage = false;
    String outgoingMessage = "OUTGOING UNINITIALIZED";
    boolean IsThereAnUnsentIncomingMessage = false;
    String incomingMessage = "INCOMING UNITIALIZED";
    boolean isInitialized = false;
    PrintWriter out;
    BufferedReader in;

    String currentInputMessage = "Test Input Message from the Server ConnectionThread";
    String previousInputMessage = null;


    Socket socket;





    public ConnectionThread(ServerSocket s) {
        System.out.println("ServerSocket passed to ConnectionThread: " + s);
        /*
         * The purpose of the constructor is to establish a socket
         * as soon as possible. All transmissions/logic/anything else
         * should happen in init() and/or run().
         */
        System.out.println("Constructing ConnectionThread.");
        try {
        Socket socket = s.accept();
        System.out.println(socket);
        }
        catch (IOException e) {
            System.out.println("Error in ConnectionThread constructor");
            System.exit(1);
        }
    }




    public void init() {
        /*
         * Everything should be set up here before run is called.
         * Once init is finished, run() should be set to begin work.
         * This is to ensure each packet is efficiently processed.
         */
        try {
            System.out.println("Establishing in and out streams:");
            System.out.println(socket);
            out = new PrintWriter(socket.getOutputStream(), true);
            System.out.println("ConnectionThread: Output Stream (PrintWriter) Established");

            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("ConnectionThread: InputStream (BufferedReader) Established");
        }
        catch (IOException e) {
            System.out.println("Error in ConnectionThread method Init.");
            System.exit(1);
        }



        isInitialized = true;
    }

并且可选地,这是测试客户端:

public class TestClient {
    static PrintWriter out;
    BufferedReader in;
    public final int PORT = 6969;
    Socket socket = null;
    InetAddress host = null;

    public TestClient() {
        out = null;
        in = null;
        socket = null;
        host = null;



    }



    public void connectToServer() {
        System.out.println("Connecting to server...");
        try {
            host = InetAddress.getLocalHost();
            socket = new Socket(host.getHostName(), PORT);
        }
        catch (Exception e) {
            System.out.println("Error establishing host/socket");
            System.exit(1);
        }




        try {
            System.out.println("Establishing I/O Streams");
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        }
        catch (Exception e) {
            System.out.println("Error establishing in/out streams");
            System.exit(1);
        }
    }


    public static void main(String[] args) {
        System.out.println("~~TestClient Alpha .1~~");
        TestClient c = new TestClient();
        c.connectToServer();
        System.out.println("Should be connected to server. Sending test message...");
        while (true) {
            System.out.println("here");
            out.println("Hello there");
        }

    }

}

最佳答案

ConnectionThread 构造函数中的“socket”变量不应该是本地变量。它正在隐藏成员变量。

习惯上在listen()循环中调用accept(),并将接受的套接字传递给ConnectionThread。

关于Java Socket I/O 流空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19459770/

相关文章:

java - 在 Java 中添加引号

java - PDFBox 锁定 JPEG 输入文件,直到应用程序退出

java - 套接字如何与常见网络 API 相关

c - 套接字 TCP 2 路连接

java - 如何在具有 android.support.v7.widget.CardView 的情况下使用 robolectric 测试 Activity ?

java - ADF : Calling a method through a managed beans in JSP

java - Android单元测试onclick方法

python - 在 asyncore 中,我如何向所有或部分客户端发送数据?

Python SSL 通信在读取时挂起,然后发出错误 54 - connection reset by peer

sockets - 使用 STARTTLS 发送电子邮件