java - 多个客户端-Java中的服务器

标签 java multithreading sockets networking executorservice

我正在使用套接字编写多个客户端-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));
}   
 }

MiniSerwer:
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();
        }
    }
}

当我尝试将消息从客户端发送到服务器时,我有很多异常(exception)。

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)

最佳答案

您的MiniSerwer类中的执行程序服务永远不会初始化。这是您的NPE的根本原因。

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

另外,在MiniSerwer中,流初始化可能会失败。您需要先验证流不为null,然后才能在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工作人员是否真的需要按现在的方式分开。

关于java - 多个客户端-Java中的服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14359036/

相关文章:

java - 线程Join()方法输出?

c++ - 当当前没有 wsarecv 时,传入数据会发生什么情况

python - 发送和接收如何在 Python 套接字中工作?

java - I/Choreographer : Skipped 8 frames! 应用程序可能在其主线程上做太多工作

java - 在SQL中对相关表使用批量插入

c# - ManualResetEvent 的可能竞争条件

c++ - 将 OpenMP 应用于 C++ 中的特定嵌套循环

ios - 特定 ip/port 的可达性测试

java - 使用spring data mongodb进行组聚合

java - 在 Java 中,有什么方法可以在给定显示名称的情况下获取区域设置?