Java多线程服务器/客户端逻辑无法正常工作

时间:2015-06-24 22:39:03

标签: java multithreading sockets serversocket

我正在尝试创建一个多线程服务器和客户端对。这两个类都继承了从公共类写入和读取的方法。我无法正常工作并且正在接收空指针异常。 这是我的代码:

//服务器和客户端的公共类

    package server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import exception.AutoException;

public class DefaultSocketClient extends Thread {
    protected ObjectInputStream ois;
    private ObjectOutputStream oos;
    private Socket sok;

    public DefaultSocketClient(Socket sok) {
        this.sok = sok;
    }
public void run() {
    openConnection();
    handleSession();
    // closeSession();
}

/*
 * this methods opens connection
 */

public void openConnection() {
    try {
        ois = new ObjectInputStream(sok.getInputStream());
        oos = new ObjectOutputStream(sok.getOutputStream());
    } catch (IOException e) {
        try {
            throw new AutoException("OpenConnectionException");
        } catch (AutoException e1) {
            e1.printStackTrace();
        }
    }
}

public void handleSession() {
    Object input;
    try {
        while ((input = ois.readObject()) != null) {
            handleInput(input);
        }
    } catch (Exception e) {
        try {
            throw new AutoException("HandleSessionException");
        } catch (AutoException e1) {
            e1.printStackTrace();
        }
    }

}

private void handleInput(Object newInput) {
    System.out.println(newInput);

}

public void sendOutput(Object newOutput) {
    try {
        oos.writeObject(newOutput);
    } catch (IOException ioe) {
        try {
            throw new AutoException("ObjectOutputException");
        } catch (AutoException e1) {
            e1.printStackTrace();
        }
    }
}

/**
 * This method closes the Session between client and server
 */
public void closeSession() {
    try {
        ois.close();
        ois.close();
        sok.close();
    } catch (IOException e) {
        try {
            throw new AutoException("SessionCloseException");
        } catch (AutoException e1) {
            e1.printStackTrace();
        }
    }

}

}

//客户端

    /*
     * creating client
     */
    public AutoClientSocket() {
        try {
            clientSocket = new Socket(InetAddress.getLocalHost(),
                    DEFAULT_PORT_NO);
            readFromConsole = new BufferedReader(new InputStreamReader(
                    System.in));
        } catch (Exception e) {
            try {
                throw new AutoException("AutoServerConnectionException");
            } catch (AutoException e1) {
                e1.printStackTrace();
            }

        }
    }

    // starting the client
    public void startAutoClient() {
        try {
            defaultSocketClient = new DefaultSocketClient(clientSocket);
            defaultSocketClient.start();
            System.out.println("Client started...");
            defaultSocketClient.closeSession();

//          performOperation();
        } catch (Exception e) {
            try {
                throw new AutoException("ConnectionException");
            } catch (AutoException e1) {
                e1.printStackTrace();
            }
        }

    }


    public void performOperation() {
        // methods for client operations.

    }

}

//服务器

public class AutoServerSocket {

private int DEFAULT_PORT_NO = 7900;
private static ServerSocket autoServer;
ObjectOutputStream oos;
ObjectInputStream ois;

private DefaultSocketClient defaultSocketClient;
BuildAuto build = new BuildAuto();
FileIO io = new FileIO();

// creating server
public AutoServerSocket() {
    try {
        autoServer = new ServerSocket(DEFAULT_PORT_NO);

        System.out.println("Server started...");
    } catch (Exception e) {
        try {
            throw new AutoException("AutoServerConnectionException");
        } catch (AutoException e1) {
            e1.printStackTrace();
        }

    }
}

// starting the server
public void startAutoServer() {
    Socket sok;
    while (true) {
        try {
            sok = autoServer.accept();
            defaultSocketClient = new DefaultSocketClient(sok);
            defaultSocketClient.start();
            System.out.println("Connection Established....");
            defaultSocketClient.sendOutput(generateAutoWelcome());
            defaultSocketClient.handleSession();
            defaultSocketClient.closeSession();
        } catch (IOException e) {
            try {
                throw new AutoException("ConnectionException");
            } catch (AutoException e1) {
                e1.printStackTrace();
            }
        }
    }
}

/**
 * This method generates Welcome message for AutoWorld
 */
private String generateAutoWelcome() {
    return "--------Welcome to AutoWorld-----------";
}

}

我在服务器上收到以下异常 - >

   Exception in thread "main" java.lang.NullPointerException
    at server.DefaultSocketClient.sendOutput(DefaultSocketClient.java:64)
    at server.AutoServerSocket.startAutoServer(AutoServerSocket.java:51)
    at driver.ServerDriver.main(ServerDriver.java:11)

在线:

  oos.writeObject(newOutput);

我显然在这里做错了,因为我无法收到客户端发送的对象。有人可以帮帮我吗?

由于

1 个答案:

答案 0 :(得分:0)

你的问题来自那里:

   defaultSocketClient = new DefaultSocketClient(sok);
   start();
   System.out.println("Connection Established....");
   sendOutput(generateAutoWelcome() + generateMainMenu());

您正在创建一个defaultSocketClient来处理客户端创建的套接字,但您不会对其执行任何操作。

替换这些行
   defaultSocketClient = new DefaultSocketClient(sok);
   defaultSocketClient.start();
   System.out.println("Connection Established....");
   defaultSocketClient.sendOutput(generateAutoWelcome() + generateMainMenu());

这应解决您的NullPointerException错误。

这里仍然存在一些架构问题。 您应该有一个服务器套接字的线程,它在sok = autoServer.accept();上循环,但您不必使用您的服务器扩展DefaultSocketClient。您的服务器将基本等待新连接并创建DefaultSocketClient的新实例。 如果您想稍后重用它们,您的服务器还应该存储DefaultSocketClient实例。否则,您应该在sendOutput()调用后调用closeSession()

这段代码似乎是出于学习目的,所以使用基本的Java套接字很好,但是如果你不想创建一个真正的/多客户/可扩展​​的客户端服务器应用程序,我建议你使用lib来实现。

Java网络库:

  • Netty真的很强大,但很难配置,并且真的很低级。
  • Kryonet易于使用一些很酷的功能,如对象序列化或主机发现。高级别的lib,可以帮助您在几行中创建客户端和服务器。