1

私はソケットを使用して複数のクライアントを作成しています-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)

さらに2つのクラスがあります(スレッド-入出力用の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();
        }
    }
}

クライアントからサーバーにメッセージを送信しようとすると、多くの例外が発生します。

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)
4

2 に答える 2

2

MiniSerwerクラス内のエグゼキュータサービスが初期化されることはありません。それがNPEの根本的な原因です。

Serwerしかし、私のコメントで述べたように、コンストラクターですべてのロジックを実行するべきではありません。コンストラクターを終了することはないため、オブジェクトが完全に初期化されることはありません。クラス全体を実行可能にし、そのロジックをオーバーライドされたrunメソッドに移動します。main次に、サーバーの実際のインスタンス化/実行に使用するメソッドを追加します。

また、ではMiniSerwer、ストリームの初期化が失敗する可能性があります。runメソッドで使用する前に、ストリームがnullでないことを検証する必要があります。または、それらの初期化ロジックをrunメソッドの先頭に移動します。

編集

また、実装にバグがありMiniSerwer、オブジェクトの入力ストリームと出力ストリームを処理するために無限の数のスレッドを生成します。

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

スレッドが不足するか、メモリが不足するか、またはその両方が発生します。正直なところ、あなたのソリューションは過剰に設計されています。インワーカーとアウトワーカーを現在のように分離する必要があるのではないかと思います。

于 2013-01-16T13:07:30.217 に答える
0

そのようなひどいことを決してしないでください。以下のコードでは、例外を2回無視しました。

最初に無視する:

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

その後は以前serversocketと同じようになりますnull

そして2番目は無視します:

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

その後try...catch socketnull以前と同じようになります。

どちらも!につながる可能性があります。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) {...}もひどいことです。しかし、この質問の括弧の後にこれを残しましょう。


于 2013-01-16T13:03:48.333 に答える