【问题标题】:Multiple clients - server in java多个客户端 - java中的服务器
【发布时间】:2013-01-16 23:09:21
【问题描述】:

我正在使用套接字来编写多个客户端-java 中的服务器应用程序。我编写了简单的客户端-服务器应用程序,一切正常,但是当我尝试将其更改为多客户端应用程序时,当我启动客户端时出现异常:

Exception in thread "pool-1-thread-1" java.lang.NullPointerException
    at MiniSerwer.run(Serwer.java:110)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:679)

我还有两个类(线程 - InWorker 和 OutWorker 用于输入和输出)。

Serwer.java(没有 InWorker 和 OutWorker):

public class Serwer {
Serwer(int port) {
ServerSocket serversocket=null;
ExecutorService exec= Executors.newCachedThreadPool();

    try {
        serversocket=new ServerSocket(port);
    } catch (IOException e) {
        e.printStackTrace();
}
    while(true) {
    Socket socket=null;
    try {
        socket = serversocket.accept();
    } catch (IOException e) {
        e.printStackTrace();
    }
    exec.execute(new MiniSerwer(socket)); // create new thread
        }
} }

MiniSerwer - 为每个客户端创建拥有线程的辅助类

class MiniSerwer implements Runnable{

    Socket socket=null;
    ExecutorService exec=null;
    ObjectOutputStream oos=null;
    ObjectInputStream ois=null;

    MiniSerwer(Socket socket) {
        this.socket=socket;
        try {
            oos=new ObjectOutputStream(socket.getOutputStream());
            oos.flush();
            ois=new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        while(true) {
            exec.execute(new InWorker(socket, ois)); // input stream
            exec.execute(new OutWorker(socket, oos)); //output stream
            Thread.yield();
        }
    }
}

我更改了我的程序,但它仍然不起作用。还有什么建议吗?

服务器:

public class Serwer implements Runnable{

ServerSocket serversocket=null;
ExecutorService exec= Executors.newCachedThreadPool();
int port;

Serwer(int port) {
    this.port=port;
}

public void run() {
    try {
        serversocket=new ServerSocket(port);
        while(true) {
            Socket socket=null;
            try {
                socket = serversocket.accept();
                exec.execute(new MiniSerwer(socket)); // create new thread
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
}
}

public static void main(String[] args) {
    int port;
    Scanner in = new Scanner(System.in);
    System.out.println("Enter the port:");
    port = in.nextInt();
    ExecutorService exec=Executors.newCachedThreadPool();
    exec.execute(new Serwer(port));
}   
 }

迷你服务器:

class MiniSerwer implements Runnable{

    Socket socket=null;
    ExecutorService exec=Executors.newCachedThreadPool();
    ObjectOutputStream oos=null;
    ObjectInputStream ois=null;

    MiniSerwer(Socket socket) {
        this.socket=socket;
    }

    public void run() {
        try {
            oos=new ObjectOutputStream(socket.getOutputStream());
            oos.flush();
            ois=new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        while(true) {
            exec.execute(new InWorker(socket, ois)); // input stream
            exec.execute(new OutWorker(socket, oos)); //output stream
            Thread.yield();
        }
    }
}

当我尝试将消息从客户端发送到服务器时,我遇到了很多例外情况。

2 秒。在服务器端连接后(我什么都不发送):

Exception in thread "pool-2-thread-1" java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:657)
    at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:943)
    at java.util.concurrent.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:992)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:679)

【问题讨论】:

  • 嗯,您的线程中某处出现了空指针异常。但仅凭这些信息,我无法告诉您更多信息。某些东西没有像它应该的那样初始化。
  • 附带说明,在其构造函数中运行服务器逻辑是非常糟糕的做法。您将希望将其移至另一种方法。我建议实现 Runnable 接口,并将逻辑移至 run 方法。

标签: java multithreading sockets networking executorservice


【解决方案1】:

MiniSerwer 类中的执行器服务永远不会初始化。这就是你的 NPE 的根本原因。

但就像我在评论中提到的那样,您不应该在其构造函数中执行所有 Serwer 逻辑。该对象永远不会完全初始化,因为您永远不会退出构造函数。使整个类 Runnable 并将该逻辑移动到重写的 run 方法。然后添加一个main 方法用于实际实例化/运行服务器。

另外,在您的MiniSerwer 中,您的流初始化可能会失败。在 run 方法中使用流之前,您需要验证流不为空。或者只是将它们的初始化逻辑移到 run 方法的开头。

编辑

您的MiniSerwer 实现中还有一个错误,您产生了无限数量的线程来处理对象输入和输出流:

while(true) {
    exec.execute(new InWorker(socket, ois)); // input stream
    exec.execute(new OutWorker(socket, oos)); //output stream
    Thread.yield();
}

您将耗尽线程、耗尽内存或两者兼而有之。老实说,您的解决方案设计过度,我怀疑 In 和 Out 工作人员是否真的需要像现在这样分开。

【讨论】:

  • 我按照您的建议做了,但程序仍然无法运行。我将它们添加到第一篇文章中。还有其他建议吗?
  • 请将例外情况也添加到您的问题中。
  • 我在第一篇文章中添加了例外。
  • @user1518451 - 您在MiniSerwer 实现中不断产生线程。查看修改。
【解决方案2】:

永远不要做这么可怕的事情。在下面的代码中,您两次忽略了异常:

先忽略:

try {
    serversocket=new ServerSocket(port);
} catch (IOException e) {
    e.printStackTrace();
}

之后serversocket 可以像以前一样是null

第二次忽略:

while(true) {
    Socket socket=null;
    try {
       socket = serversocket.accept();
     } catch (IOException e) {
        e.printStackTrace();
     }
     exec.execute(new MiniSerwer(socket)); // create new thread
}

之后try...catchsocket也可以像以前一样是null

这两件事都可能导致NullPointerException

像这样修复它:

try {
    serversocket=new ServerSocket(port);
    while(true) {
        Socket socket=null;
        try {
            socket = serversocket.accept();
            exec.execute(new MiniSerwer(socket)); // create new thread
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
} catch (IOException e) {
    e.printStackTrace();
}

UPD: 这个:while(true) {...} 也是可怕的东西。但是让我们把这个放在这个问题的括号之后。


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-09
    • 2022-06-16
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 2015-02-19
    相关资源
    最近更新 更多