2016-04-14 10 views
2

マルチスレッドデュプレックスチャットサーバーを作成しようとしています。コードをスレッドに移動する前に正常に動作しましたが、スレッドがソケットにアクセスしようとするたびに、「SocketException:SocketExceptionが発生しました」というメッセージが表示されます。新しいスレッドに入るとすぐにソケットが閉じられる

私の先生と私は理解できません。 (先生は私よりもJavaが少ないと知っています;彼はCの人です)。ソケットが開いているようですが、スレッドに入るとすぐに閉じます。

私は間違っていますか?

クライアントコード:

public class Client { 
    public static void main(String[] args) throws IOException { 
     String hostName = "localhost"; 
     int portNumber = 6969; 
     try (
       Socket socket = new Socket(hostName, portNumber); 
     ) { 
      System.out.println("Chat connected"); 
      //Sender 
      if (!socket.isClosed()) 
       new Thread(new Sender(socket)).start(); 
      //Receiver 
      if (!socket.isClosed()) 
       new Thread(new Receiver(socket)).start(); 
     } catch (SocketException e) { 
      System.out.println("Connection terminated unexpectedly"); 
     } 
    } 
} 

Serverコード:

public class Server { 
    public static void main(String[] args) throws IOException { 
     int portNumber = 6969; 
     try (
       ServerSocket serverSocket = new ServerSocket(portNumber); 
       Socket clientSocket = serverSocket.accept(); 
     ) { 
      //Receiver 
      if (!clientSocket.isClosed()) 
       new Thread(new Receiver(clientSocket)).start(); 
      //Sender 
      if (!clientSocket.isClosed()) 
       new Thread(new Sender(clientSocket)).start(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

レシーバスレッドコード:

class Receiver implements Runnable { 

    private Socket socket; 

    Receiver(Socket s) throws IOException { 
     socket = s; 
    } 

    @Override 
    public void run() { 
     try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { 
      String received; 
      do { 
       received = in.readLine(); 
       if (received == null) break; 
       System.out.println("Them: " + received); 
      } while (!received.contains("/dropmic")); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

送信者スレッドコード:

class Sender implements Runnable { 
    private Socket socket; 

    Sender(Socket s) throws IOException { 
     socket = s; 
    } 

    @Override 
    public void run() { 
     try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 
      BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { 
      String sent; 
      do { 
       System.out.print("You: "); 
       sent = stdIn.readLine(); 
       if (sent == null) break; 
       out.println(sent); 
      } while (!sent.contains("/dropmic")); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

サーバー出力:

java.net.SocketException: Socket is closed 
    at java.net.Socket.getOutputStream(Socket.java:943) 
    at Sender.run(Sender.java:16) 
    at java.lang.Thread.run(Thread.java:745) 
java.net.SocketException: Socket closed 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) 
    at java.net.SocketInputStream.read(SocketInputStream.java:170) 
    at java.net.SocketInputStream.read(SocketInputStream.java:141) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) 
    at java.io.InputStreamReader.read(InputStreamReader.java:184) 
    at java.io.BufferedReader.fill(BufferedReader.java:161) 
    at java.io.BufferedReader.readLine(BufferedReader.java:324) 
    at java.io.BufferedReader.readLine(BufferedReader.java:389) 
    at Receiver.run(Receiver.java:19) 
    at java.lang.Thread.run(Thread.java:745) 

Process finished with exit code 0 

クライアント出力(まだ実行中):

Chat connected 
You: java.net.SocketException: Socket is closed 
    at java.net.Socket.getInputStream(Socket.java:903) 
    at Receiver.run(Receiver.java:16) 
    at java.lang.Thread.run(Thread.java:745) 
+1

出力を投稿できますか? – Natecat

+0

はい、編集元の投稿 – lbenedetto

答えて

4

あなたがしよう - と、リソース文を使用して、リソースのようにソケットを入れています。しかし、新しいスレッドを作成すると、このtry-with-resourcesはコードの最後に到達し、ソケットを閉じます。あなたのソケットを実際のtry文の中に入れ、手動で閉じてこれを修正してください。

関連する問題