Simple java chat server that only broadcasts to other clients not sender

匿名 (未验证) 提交于 2019-12-03 10:09:14

问题:

I have been working through a tutorial for a simple java chat server and would like to modify it so that it doesn't echo back to the original sender. I have tried to mod it with my limited skills but nothing I know has worked and any help would be appreciated.

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) {             }         }     } } } 

Here is the client

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:

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) {             }         }     } }  }  

i have made some changes to your program , problem with your earlier code was that you cant identify users connected. now im using a hashmap object to store the printwriters and the key im using in hashmap is users inetaddress which is unique from pc to pc. maybe you should try this one



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!