2017-08-30 7 views
0

私の質問はタイトルの意味です。複数のクライアントを処理するインスタントメッセンジャーを作成しようとする私の試みは機能しません。私はすべてのWebサイトのようにスレッドを使用して試してみる必要があります。私は本当に奇妙な結果を得る。複数のクライアントが動作していないJavaインスタントメッセンジャー

すべてのメッセージを受け取るサーバーと2番目のクライアント。ただし、参加する最初のクライアントは何も取得しません。それはそれ自身のメッセージを含んでいます。ここで

は私のコードです:

サーバー:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

public class Server extends JFrame { 

JTextField userText; 
static JTextArea dialog; 

ServerSocket server; 
Socket socket; 

static boolean isClosed; 

public Server() { 
    super("server"); 

    addWindowListener(new WindowAdapter() { 
     public void windowClosed(WindowEvent e) { 
      isClosed = true; 
     } 
    }); 

     userText = new JTextField(); 
     userText.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       ServerThread.sendObject("\nSERVER: "+e.getActionCommand()); 
       log("\nSERVER: "+e.getActionCommand()); 
       userText.setText(""); 
      } 
     }); 

     dialog = new JTextArea(); 
     dialog.setEditable(false); 

     add(new JScrollPane(dialog),BorderLayout.CENTER); 
     add(userText,BorderLayout.SOUTH); 

     setSize(300,150); 
     setVisible(true); 
} 

public static void main(String args[]) { 
    Server s = new Server(); 
    s.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    s.initNetwork(); 
} 

public void initNetwork() { 
    try{ 
    server = new ServerSocket(1357); 

    while(true) { 
     try{ 

      ServerThread thread = new ServerThread(server.accept()); 
      thread.start(); 
     }catch(Exception eof) { 
      System.out.println("Server disconnected"); 
     } 
    } 
    }catch(IOException io) { 
     io.printStackTrace(); 
    }finally{ 
     try{ 
     server.close(); 
     }catch(IOException io) { 
      io.printStackTrace(); 
     } 
    } 


} 
public static void log(String msg) { 
    dialog.append(msg); 
} 


} 

class ServerThread extends Thread{ 

Socket connection; 

ObjectInputStream input; 
static ObjectOutputStream output; 

String message; 

public ServerThread(Socket s) { 
    connection = s; 
    try{ 
    setupStreams(); 
    }catch(IOException io) { 
     io.printStackTrace(); 
    } 
} 

public void run() { 
    try{ 
     readInput(); 
    }catch(IOException io) { 
     io.printStackTrace(); 
    }finally{ 
     try{ 
     input.close(); 
     output.close(); 
     connection.close(); 
     }catch(IOException io) { 
      io.printStackTrace(); 
     } 
    } 
} 
public void setupStreams() throws IOException{ 
    input = new ObjectInputStream(connection.getInputStream()); 
    output = new ObjectOutputStream(connection.getOutputStream()); 
    output.flush(); 
} 

public void readInput() throws IOException { 
    while(!Server.isClosed) { 
     try{ 
     message = (String)input.readObject(); 
     Server.log(message); 
     sendObject(message); 
     }catch(ClassNotFoundException c) { 
      c.printStackTrace(); 
     } 
    } 
} 

public static void sendObject(Object obj) { 
    SwingUtilities.invokeLater(new Thread() { 
     public void run() { 
      try{ 
      output.writeObject(obj); 
      }catch(IOException io) { 
       io.printStackTrace(); 
      } 
     } 
    }); 

} 
} 

クライアント:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 

public class Client extends JFrame{ 

JTextField userText; 
static JTextArea dialog; 

static boolean isClosed; 

public Client() { 
    super("client"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    addWindowListener(new WindowAdapter() { 
     public void windowClosed(WindowEvent e) { 
      isClosed = true; 
     } 
    }); 

    userText = new JTextField(); 
    userText.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      sendObject("\nClient: "+e.getActionCommand()); 
      userText.setText(""); 
     } 
    }); 


    dialog = new JTextArea(); 
    dialog.setEditable(false); 

    add(userText,BorderLayout.SOUTH); 
    add(new JScrollPane(dialog),BorderLayout.CENTER); 

    setSize(300,150); 
    setVisible(true); 

    new ClientThread("127.0.0.1"); 
} 

public static void main(String args[]) { 
    Client c = new Client(); 
} 
public void sendObject(Object obj) { 
    try{ 
    ClientThread.output.writeObject(obj); 
    }catch(IOException io) { 
     io.printStackTrace(); 
    } 
} 
} 

class ClientThread extends Thread{ 

private Socket socket; 
private ObjectInputStream input; 
static ObjectOutputStream output; 

String message; 

public ClientThread(String ip) { 
    try{ 
     socket = new Socket(ip,1357); 

     output = new ObjectOutputStream(socket.getOutputStream()); 
     output.flush(); 
     input = new ObjectInputStream(socket.getInputStream()); 

     start(); 

    }catch(IOException io) { 
     io.printStackTrace(); 
    } 
} 

public void run() { 
    try{ 
    while(!Client.isClosed) { 
     try{ 
     message = (String)input.readObject(); 
     log(message); 
     }catch(ClassNotFoundException c) { 
      c.printStackTrace(); 
     } 
    } 
    }catch(IOException io) { 
     io.printStackTrace(); 
    }finally{ 
     try{ 
      input.close(); 
      output.close(); 
      socket.close(); 
     }catch(IOException io) { 
      io.printStackTrace(); 
     } 
    } 
} 

public void log(String msg) { 
    Client.dialog.append(msg); 
} 

} 

なぜ、この作業とどのように私はこの問題を解決することができないのですか?ありがとうございました!

答えて

1

マルチスレッドプログラミングを学ぶ必要があります。 ObjectOutputStreamを格納するために、ServerThreadクラスに静的変数を作成しました。静的変数はクラスレベルの変数で、ServerThreadのすべてのインスタンスに対して1つの変数が存在することを意味します。したがって、2番目のクライアントが接続すると、グローバルであるServerThreadObjectOutputStreamが置き換えられます。それで、第二のクライアントがすべてのメッセージを受け取るのです。現時点では、ServerThread.outputをstatic以外の変数に変更し、sendObjectメソッドのシグネチャをpublic void sendObject(Object obj, final ObjectOutputStream output)に変更し、sendObject(message, output);と呼び出してください。

import javax.swing.JTextArea; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

public class Server extends JFrame { 

JTextField userText; 
static JTextArea dialog; 

ServerSocket server; 
Socket socket; 

static boolean isClosed; 

public Server() { 
    super("server"); 

    addWindowListener(new WindowAdapter() { 
     public void windowClosed(WindowEvent e) { 
      isClosed = true; 
     } 
    }); 

     userText = new JTextField(); 
     userText.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       ServerThread.sendObject("\nSERVER: "+e.getActionCommand()); 
       log("\nSERVER: "+e.getActionCommand()); 
       userText.setText(""); 
      } 
     }); 

     dialog = new JTextArea(); 
     dialog.setEditable(false); 

     add(new JScrollPane(dialog),BorderLayout.CENTER); 
     add(userText,BorderLayout.SOUTH); 

     setSize(300,150); 
     setVisible(true); 
} 

public static void main(String args[]) { 
    Server s = new Server(); 
    s.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    s.initNetwork(); 
} 

public void initNetwork() { 
    try{ 
    server = new ServerSocket(1357); 

    while(true) { 
     try{ 

      ServerThread thread = new ServerThread(server.accept()); 
      thread.start(); 
     }catch(Exception eof) { 
      System.out.println("Server disconnected"); 
     } 
    } 
    }catch(IOException io) { 
     io.printStackTrace(); 
    }finally{ 
     try{ 
     server.close(); 
     }catch(IOException io) { 
      io.printStackTrace(); 
     } 
    } 


} 
public static void log(String msg) { 
    dialog.append(msg); 
} 


} 

class ServerThread extends Thread{ 

Socket connection; 

ObjectInputStream input; 
ObjectOutputStream output; 

String message; 

public ServerThread(Socket s) { 
    connection = s; 
    try{ 
    setupStreams(); 
    }catch(IOException io) { 
     io.printStackTrace(); 
    } 
} 

public void run() { 
    try{ 
     readInput(); 
    }catch(IOException io) { 
     io.printStackTrace(); 
    }finally{ 
     try{ 
     input.close(); 
     output.close(); 
     connection.close(); 
     }catch(IOException io) { 
      io.printStackTrace(); 
     } 
    } 
} 
public void setupStreams() throws IOException{ 
    input = new ObjectInputStream(connection.getInputStream()); 
    output = new ObjectOutputStream(connection.getOutputStream()); 
    output.flush(); 
} 

public void readInput() throws IOException { 
    while(!Server.isClosed) { 
     try{ 
     message = (String)input.readObject(); 
     Server.log(message); 
     sendObject(message, output); 
     }catch(ClassNotFoundException c) { 
      c.printStackTrace(); 
     } 
    } 
} 

public void sendObject(Object obj, final ObjectOutputStream output) { 
    SwingUtilities.invokeLater(new Thread() { 
     public void run() { 
      try{ 
      output.writeObject(obj); 
      }catch(IOException io) { 
       io.printStackTrace(); 
      } 
     } 
    }); 

} 
} 
+0

ありがとうございました。しかし、OutputStream 'output'はServerクラスからアクセスできないので、TextFieldイベントリスナーからどのようにアクセスするのですか? – Max

関連する問題