2016-04-22 15 views
1

シンプルなJavaチャットサーバーのチュートリアルを行っています。元の送信者にエコーバックしないように修正したいと思います。私は限られたスキルでそれを改造しようとしましたが、私が知っていることは何も働いておらず、どんな助けもありがたいです。送信者ではない他のクライアントにのみブロードキャストするシンプルなJavaチャットサーバー

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.HashSet; 


public class ChatServer { 


// Port that the server listens on. 
private static final int PORT = 9001; 


// Creates names 
private static HashSet<String> names = new HashSet<String>(); 


// Creates writers 
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>(); 

// Main method, which just listens on a port and spawns handler threads. 
public static void main(String[] args) throws Exception { 
    System.out.println("The Chatty server is running."); 
    ServerSocket listener = new ServerSocket(PORT); 
    try { 
     while (true) { 
      new Handler(listener.accept()).start(); 
     } 
    } finally { 
     listener.close(); 
    } 
} 


private static class Handler extends Thread { 
    private String name; 
    private Socket socket; 
    private BufferedReader in; 
    private PrintWriter out; 


    public Handler(Socket socket) { 
     this.socket = socket; 
    } 


    public void run() { 
     try { 

// Create character streams for the socket. 
      in = new BufferedReader(new InputStreamReader(
       socket.getInputStream())); 
      out = new PrintWriter(socket.getOutputStream(), true); 

    // Request a name from this client. Keep requesting until 
    // a name is submitted that is not already used. Note that 
    // checking for the existence of a name and adding the name 
      // must be done while locking the set of names. 
      while (true) { 
       out.println("SUBMITNAME"); 
       name = in.readLine(); 
       if (name == null) { 
        return; 
       } 
       synchronized (names) { 
        if (!names.contains(name)) { 
         names.add(name); 
         break; 
        } 
       } 
      } 

      // Now that a successful name has been chosen, add the 
      // socket's print writer to the set of all writers so 
      // this client can receive broadcast messages. 
      out.println("NAMEACCEPTED"); 
      writers.add(out); 

      // Accept messages from this client and broadcast them. 
      // Ignore other clients that cannot be broadcasted to. 
      while (true) { 
       String input = in.readLine(); 
       if (input == null) { 
        return; 
       } 
// Where to add the section that prevents sending to original sender? 
       for (PrintWriter writer : writers) { 
        writer.println("MESSAGE " + name + ": " + input); 
        System.out.println(writer); 
        System.out.println("MESSAGE " + name + ": " + input); 
       } 
      } 


     } catch (IOException e) { 
      System.out.println(e); 
     } finally { 
      // This client is going down! Remove its name and its print 
      // writer from the sets, and close its socket. 
      if (name != null) { 
       names.remove(name); 
      } 
      if (out != null) { 
       writers.remove(out); 
      } 
      try { 
       socket.close(); 
      } catch (IOException e) { 
      } 
     } 
    } 
} 
} 

は、ここで私はあなたのプログラムにいくつかの変更を行った

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.Socket; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 


public class ChatClient { 

BufferedReader in; 
PrintWriter out; 
JFrame frame = new JFrame("Chatty"); 
JTextField textField = new JTextField(40); 
JTextArea messageArea = new JTextArea(8, 40); 

public ChatClient() { 

// Layout GUI 
    textField.setEditable(false); 
    messageArea.setEditable(false); 
    frame.getContentPane().add(textField, "North"); 
    frame.getContentPane().add(new JScrollPane(messageArea), "Center"); 
    frame.pack(); 

// Add Listeners 
    textField.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent e) { 
      out.println(textField.getText()); 
      textField.setText(""); 
     } 
    }); 
} 


// Prompt for and return the desired screen name. 
private String getName() { 
    return JOptionPane.showInputDialog(
     frame, 
     "Choose a screen name:", 
     "Screen name selection", 
     JOptionPane.PLAIN_MESSAGE); 
} 


// Connects to the server then enters the processing loop. 
    private void run() throws IOException { 

    // Make connection and initialize streams 
    String serverAddress = "0"; 
    Socket socket = new Socket(serverAddress, 9001); 
    in = new BufferedReader(new InputStreamReader(
     socket.getInputStream())); 
    out = new PrintWriter(socket.getOutputStream(), true); 

// Process all messages from server, according to the protocol. 
    while (true) { 
     String line = in.readLine(); 
     if (line.startsWith("SUBMITNAME")) { 
      out.println(getName()); 
     } else if (line.startsWith("NAMEACCEPTED")) { 
      textField.setEditable(true); 
     } else if (line.startsWith("MESSAGE")) { 
      messageArea.append(line.substring(8) + "\n"); 
     } 
    } 
} 


// Runs the client as an application with a closeable frame. 

public static void main(String[] args) throws Exception { 
    ChatClient client = new ChatClient(); 
    client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    client.frame.setVisible(true); 
    client.run(); 
} 
}  
+1

メッセージがサーバによって受信されたことをユーザが知るようにエコーバックするのは正常です。 – markspace

+1

メッセージを受け取ったときに、クライアント接続を 'Map 'に入れてください。マークスペースが指摘するように、メッセージをクライアントに送り返すことは珍しいことではありません。 –

+0

私は、コードに何が起きているのかをより深く理解しようとしています。これはシステムに追加する簡単なコントロールだと思っていました。 – Covec

答えて

0
public class ChatServer { 


// Port that the server listens on. 
private static final int PORT = 9001; 


// Creates names 
private static HashSet<String> names = new HashSet<String>(); 


// Creates writers 
private static HashMap<String,PrintWriter> writers = new HashMap<String,PrintWriter>(); 

// Main method, which just listens on a port and spawns handler threads. 
public static void main(String[] args) throws Exception { 
    System.out.println("The Chatty server is running."); 
    ServerSocket listener = new ServerSocket(PORT); 
    try { 
     while (true) { 
      new Handler(listener.accept()).start(); 
     } 
    } finally { 
     listener.close(); 
    } 
} 


private static class Handler extends Thread { 
    private String name; 
    private Socket socket; 
    private BufferedReader in; 
    private PrintWriter out; 


    public Handler(Socket socket) { 
     this.socket = socket; 
    } 


    public void run() { 
     try { 

// Create character streams for the socket. 
      in = new BufferedReader(new InputStreamReader(
       socket.getInputStream())); 
      out = new PrintWriter(socket.getOutputStream(), true); 
      String keyForEachUser = socket.getInetAddress().toString(); 

    // Request a name from this client. Keep requesting until 
    // a name is submitted that is not already used. Note that 
    // checking for the existence of a name and adding the name 
      // must be done while locking the set of names. 
      while (true) { 
       out.println("SUBMITNAME"); 
       name = in.readLine(); 
       if (name == null) { 
        return; 
       } 
       synchronized (names) { 
        if (!names.contains(name)) { 
         names.add(name); 
         break; 
        } 
       } 
      } 

      // Now that a successful name has been chosen, add the 
      // socket's print writer to the set of all writers so 
      // this client can receive broadcast messages. 
      out.println("NAMEACCEPTED"); 
      writers.put(keyForEachUser,out); 

      // Accept messages from this client and broadcast them. 
      // Ignore other clients that cannot be broadcasted to. 
      while (true) { 
       String input = in.readLine(); 
       if (input == null) { 
        return; 
       } 
// Where to add the section that prevents sending to original sender? 

       for (String key : writers.keySet()) { 
         if (key.equalsIgnoreCase(keyForEachUser)) { 
         //original user founf not sending the data 
         }else{ 
         PrintWriter writer = writers.get(key); //getting the correct output stream 
         writer.println("MESSAGE " + name + ": " + input); 
         System.out.println(writer); 
         System.out.println("MESSAGE " + name + ": " + input); 
         } 
       } 

       } 


     } catch (IOException e) { 
      System.out.println(e); 
     } finally { 
      // This client is going down! Remove its name and its print 
      // writer from the sets, and close its socket. 
      if (name != null) { 
       names.remove(name); 
      } 
      if (out != null) { 
       writers.remove(out); 
      } 
      try { 
       socket.close(); 
      } catch (IOException e) { 
      } 
     } 
    } 
} 

} 

クライアントで、以前のコードの問題は、あなたが接続しているユーザーを識別傾けるということでした。今では、ハッシュマップオブジェクトを使用してプリントライターを保存し、ハッシュマップで使用するキーは、pcからpcまでユニークなユーザーinetaddressです。多分あなたはこの1つを試してみてください

+0

残念ながら、それは動作しませんでした。実行中のクライアントは同じコンピュータ上で実行されています。 – Covec

+0

エラーが発生したか、以前の出力が得られました.1台のコンピュータしか持たないので、1台のクライアントしか稼動していません。 – Priyamal

+0

1台または複数台のクライアントに出力がありません。エラーなしでコンパイルします。単一のクライアントは正常に機能していると出力を出さないので、同じコンピュータ上で2つのクライアントを実行してその機能をテストする必要があるため、ネットアドレスがキーとして機能しない可能性があります。 – Covec

関連する問題