2017-04-15 13 views
1

これは私が書いた最初のJavaソケット/マルチスレッドアプリケーションです。したがって、あなたが目撃しようとしている凶悪なコードをお詫びしたいと思います。Javaマルチスレッドサーバ - 高いCPU使用率とjava.net.SocketException:ソケットクローズ

とにかく、このコードは基本的なものとみなされます。これは、一度に多くのクライアントからの接続を可能にする標準的なサーバーです。また、サーバーにはサーバーを閉じるStopServerボタンだけのインターフェースがありますが、クライアントはサーバーに接続してから接続を解除する以外に何もしません。私は単純にサーバクラスを実行する場合

は今、それは大丈夫だ、「悪い」何も起こりませんし、私はそれを閉じたときに、それはしかし、細かい閉じます。その後、私は、サーバーのクラスを実行する場合、および:

1私は一度クライアントクラスを実行し、サーバーを閉鎖しようと、クライアントの切断をしましょう、と、私はエラーを取得する:

java.net.SocketException: socket closed

2:各クライアントには、CPU使用率の〜30から35パーセントで約追加されます簡単な実行であり、その利用率は「Java(TM)Platform SE Binary」プロセスにとどまります。これはサーバー引き続き実行されます。クライアントをサーバーに接続させて30秒とすれば、CPU使用率は100%に達します。

また、私は少し研究をしましたが、「ソケットクローズ例外」とは、ソケットを閉じて使用しようとし続けたことを意味します。また、サーバーの処理方法にも問題があります。切断されたクライアント。上記のコードの行65にある:

サーバー

import java.sql.*; 
import java.net.*; 
import java.io.*; 
import java.util.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 



public class Server extends JFrame 
    { private Connection con; 
    private static int port = 44444; 
    private boolean serverKeepGoing; 
    private static int uniqueId; 
    private ArrayList<ClientThread> al; 
    private ServerSocket serverSocket; 
    public Scanner keyboard = new Scanner(System.in); 

    public static void main(String[] args) throws IOException 
     { Server server = new Server(port); 
      server.start(); 

     } 


    public void ServerClose() 
     { 
      serverKeepGoing = false; 
      try 
      { 
      for(int i = 0; i < al.size(); ++i) 
       { ClientThread tc = al.get(i); 
       try 
        { 
        tc.in.close(); 
        tc.out.close(); 
        tc.socket.close(); } 
       catch(IOException e) { e.printStackTrace(); } 

       serverSocket.close();} 

      }catch(Exception e) { e.printStackTrace(); } 
     } 


    public Server (int port) 
     { 

     serverInterface(); 
     al = new ArrayList<ClientThread>(); 
     } 




    public void start() 
      { serverKeepGoing = true; 

      try 
      { serverSocket = new ServerSocket(port); 
       System.out.println("Server is running!"); 

       while(serverKeepGoing) 
       { Socket socket = serverSocket.accept(); // accept connection. LINE 65 
        // ^ALSO :java.net.SocketException: socket closed 
        // if I was asked to stop 



       if(!serverKeepGoing) 
        { ServerClose(); break;} 

        ClientThread t = new ClientThread(socket); // make a thread of it 
        al.add(t);         // save it in the ArrayList 
        t.start(); 


       } 



       ServerClose(); // means the server has got to be closed 

      }catch (IOException e) { e.printStackTrace(); System.out.println("Error in method start"); } 


     } 


    public synchronized void remove(int id) { 
     // scan the array list until we found the Id 
     for(int i = 0; i < al.size(); ++i) { 
      ClientThread ct = al.get(i); 
      // found it 
      if(ct.id == id) { 
       al.remove(i); 
       return; 
      } 
     } 
    } 



    class ClientThread extends Thread 
     { // the socket where to listen/talk 
     Socket socket; 
     BufferedReader in; 
     PrintWriter out; 
     boolean clientKeepGoing; 
     // my unique id (easier for deconnection) 
     int id; 


     public ClientThread(Socket socket) 
      { id = ++uniqueId; 
      this.socket = socket; 

      try 
      { 

       in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       out = new PrintWriter(socket.getOutputStream(), true); 


      } 
      catch (IOException e) { return; } 


     } 


     public void run() 
      { 
      boolean clientKeepGoing = true; 
      while(clientKeepGoing) 
       { try 
        { 





        }catch(Exception e){ e.printStackTrace(); } 


       } 
      // remove myself from the arrayList containing the list of the 
      // connected Clients 
      remove(id); 
      close(); 
      } 


     // try to close everything 
     private void close() 
      { clientKeepGoing = false; 
      try { 
       if(out != null) out.close(); 
      } 
      catch(Exception e) {} 
      try { 
       if(in != null) in.close(); 
      } 
      catch(Exception e) {}; 
      try { 
       if(socket != null) socket.close(); 
      } 
      catch (Exception e) {} 

      } 


    } 

    public void serverInterface(){ 
     JFrame frame = new JFrame("Server"); 

     frame.setLayout(null); 

     int windowWidth = 300; 
     int windowHeight = 400; 

     frame.setBounds(250, 150, windowWidth, windowHeight); 

     JButton stopServer = new JButton("Stop server"); 

     stopServer.setFocusable(false); 

     stopServer.setBounds(60, 275, 175, 20); 

     frame.add(stopServer); 

     stopServer.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) 
      { 
       ServerClose(); 
       System.exit(1); 
      } 
     }); 



     frame.setResizable(false); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 


    public void windowClosing(WindowEvent e) 
    { ServerClose(); 
     System.exit(1); 
    } 
    public void windowClosed(WindowEvent e) {} 
    public void windowOpened(WindowEvent e) {} 
    public void windowIconified(WindowEvent e) {} 
    public void windowDeiconified(WindowEvent e) {} 
    public void windowActivated(WindowEvent e) {} 
    public void windowDeactivated(WindowEvent e) {} 
    } 

'ソケットが閉じjava.net.SocketExceptionが:'

は、ここでは、コードです。これは私が現在構築しています、アプリケーション全体のほんの断片である、私はサーバ・クライアント通信としなければならなかったものだけを投稿してみましたので、私は削除したことを

クライアント

import java.net.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.io.*; 
import java.util.*; 
import javax.swing.*; 

public class Client 
    { private BufferedReader in; 
    private PrintWriter out; 
    private Socket socket; 
    private int port; 
    private String server; 


    public static void main(String[] args) 
     { int portNumber = 44444; 
     String serverAddress = "localhost"; 

     Client client = new Client(serverAddress, portNumber); 

     if(!client.start()) 
      return;  

     } 


    public Client(String server, int port) 
     { this.server = server; 
     this.port = port; 
     } 



    public boolean start() 
     { // try to connect to the server 
     try { 
      socket = new Socket(server, port); 
     } 
     // if it failed not much I can do 
     catch(Exception ec) { 
      System.out.println("Error connectiong to server:" + ec); 
      ec.printStackTrace(); 
      return false; 
     } 


     try 
     { 
      in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      out = new PrintWriter(socket.getOutputStream(), true);; 
     } 
     catch (IOException eIO) { 
      System.out.println("Exception creating new Input/output Streams: " + eIO); 
      eIO.printStackTrace(); 
      return false; 
     } 

     // creates the Thread to listen from the server 
     new ListenFromServer().start(); 


     // success we inform the caller that it worked 
     return true; 
    } 





    class ListenFromServer extends Thread 
     { 
     public void run() 
      { while(true) 
       { 




       disconnect() ; 
       break; 
       } 
      } 


     } 

    public void disconnect() 
     { try { 
      if(in != null) in.close(); 
     } 
     catch(Exception e) {} // not much else I can do 
     try { 
      if(out != null) out.close(); 
     } 
     catch(Exception e) {} // not much else I can do 
     try{ 
      if(socket != null) socket.close(); 
     } 
     catch(Exception e) {} // not much else I can do 
     } 

    } 

注意他のすべて、私はあなたが多分どのような目的を持っていないものを見る場合にはこのことを言って、私はおそらくそれを私があると考えて、私は質問が重複としてマークされてしまっていることがわかり


を、削除することを省略します不公正。まず、「類似の」質問では、問題は明らかで、ソケットを閉じたアウトポットストリームが閉じられていたが、ソケットはまだ使用されていたのに対し、私のプログラムはすべてすべてを閉じていた。私はいわゆる「類似の」質問から何の答えも得られません。

+0

重複していますが、関連するコードをすべて省略していて、ループ内の 'IOException' *は無視しています。 – EJP

+0

@EJPまあ、私が上記のことが起こった理由を知りたいので、問題に関連するコードの部分を追加することが最善のアプローチだと思う。 第2に、「ループ内のIOExceptionを無視する」ということをさらに詳しく説明できれば、それを修正するために何をすればよいのか、ということに感謝します。 第3に、重複していることがわかりません。問題は明らかです。ソケットの出力ストリームを閉じてから、入力を使用しようとしていますが、同時にすべてを閉じます。さらに、私はまた、彼の質問では解決されていないCPUの問題を持っています。 –

+0

これは、ソケットをクローズしてから使用し続け、例外を無視するために発生します。一生懸命努力する。 'ループ内のIOException'を無視するという解決策は、ループ内でIOExceptionを無視する場所を見つけて*停止*することです。そこには白黒でいます。私はそれを見つけました。あなたもそうすることができます。あなたは結局それを書きました。 – EJP

答えて

2

CPU使用率が高いのは、クライアントスレッドが空のループでCPUを焼く以外に何もしていないためです。 SocketExceptionについては、計画どおりに動作するので、キャッチして処理してください。

+0

さて、クライアントは自動的に切断する前に1秒間だけ実行されるはずです。 CPUを「解放」してはいけませんか?また、「ソケット例外」については、コードに何か間違っているとは必ずしも言えませんが、それは起こるのが自然なことですか? –

+0

そして完全なプログラムでは、クライアントにはいくつかの機能を持つインターフェースもあります。私が言ったように、クライアントを30秒以上接続すると、CPUは100%になります。 –

+1

コードには間違いがありますが、ソケット例外は閉じたソケットを使用しようとする通常の結果に過ぎません。 CPU使用率が高いのは、ビジー待機を行う通常の結果です。すべてのコードを削除し、適切なチュートリアルを見つけてから正しく再実行することをお勧めします。 – Kayaman