multithreading聊天服务器

我是Threads的新手。 我试图从服务器向客户端广播消息。但我不能。 看起来服务器总是监听新的连接。但我可以使用客户端终端向其他客户端发送消息。 我的问题是如何在同时收听时允许输入。 这是代码。

MultiThreadChatServerSync.java

import java.io.InputStreamReader; import java.io.DataInputStream; import java.io.PrintStream; import java.io.IOException; import java.net.Socket; import java.net.ServerSocket; import java.io.BufferedReader; public class MultiThreadChatServerSync extends Thread { private static ServerSocket serverSocket = null; private static Socket clientSocket = null; private static Socket serversSocket = null; private static DataInputStream iss = null; private static PrintStream oss = null; private static final int maxClientsCount = 10; private static final clientThread[] threads = new clientThread[maxClientsCount]; public static void main(String args[]) { int num = 0; int portNumber = 2222; if (args.length < 1) { System.out.println("Usage: java MultiThreadChatServerSync "Nowusingnumber=" + portNumber); } else { portNumber = Integer.valueOf(args[0]).intValue(); } try { serverSocket = new ServerSocket(portNumber); } catch (IOException e) { System.out.println(e); } DataInputStream iss = null; while (true) { try { System.out.println("5"); num++; // I want to be able to input text here to the server which will be // send to different clients // But I cannot clientSocket = serverSocket.accept(); int i = 0; for (i = 0; i < maxClientsCount; i++) { if (threads[i] == null) { System.out.println("6"); (threads[i] = new clientThread(clientSocket, threads)) .start(); break; } } if (i == maxClientsCount) { PrintStream os = new PrintStream(clientSocket.getOutputStream()); os.println("Server too busy. Try later."); os.close(); clientSocket.close(); } } catch (IOException e) { System.out.println(e); } } } } class clientThread extends Thread { private String clientName = null; private DataInputStream is = null; private PrintStream os = null; private Socket clientSocket = null; private final clientThread[] threads; private int maxClientsCount; public clientThread(Socket clientSocket, clientThread[] threads) { this.clientSocket = clientSocket; this.threads = threads; maxClientsCount = threads.length; } public void run() { int maxClientsCount = this.maxClientsCount; clientThread[] threads = this.threads; try { is = new DataInputStream(clientSocket.getInputStream()); os = new PrintStream(clientSocket.getOutputStream()); String name; while (true) { os.println("Enter your name."); name = is.readLine().trim(); if (name.indexOf('@') == -1) { break; } else { os.println("The name should not contain '@' character."); } } os.println("Welcome " + name + " to our chat room.\nTo leave enter /quit in a new line."); synchronized (this) { for (int i = 0; i < maxClientsCount; i++) { if (threads[i] != null && threads[i] == this) { clientName = "@" + name; break; } } for (int i = 0; i  1 && words[1] != null) { words[1] = words[1].trim(); if (!words[1].isEmpty()) { synchronized (this) { for (int i = 0; i < maxClientsCount; i++) { if (threads[i] != null && threads[i] != this && threads[i].clientName != null && threads[i].clientName.equals(words[0])) { threads[i].os.println(" " + words[1]); this.os.println(">" + name + "> " + words[1]); break; } } } } } } else { synchronized (this) { for (int i = 0; i < maxClientsCount; i++) { if (threads[i] != null && threads[i].clientName != null) { threads[i].os.println(" " + line); } } } } } synchronized (this) { for (int i = 0; i < maxClientsCount; i++) { if (threads[i] != null && threads[i] != this && threads[i].clientName != null) { threads[i].os.println("*** The user " + name + " is leaving the chat room !!! ***"); } } } os.println("*** Bye " + name + " ***"); synchronized (this) { for (int i = 0; i < maxClientsCount; i++) { if (threads[i] == this) { threads[i] = null; } } } is.close(); os.close(); clientSocket.close(); } catch (IOException e) { } } } 

  1. 你应该在后台线程中监听客户端。 你的代码当前没有这样做,所以你的服务器实际上是在无休止的while (true)循环中锁定的。
  2. 您应该重构您的代码,以便您的方法不会那么庞大和笨拙。
  3. 您应该重构您的代码,以便您的主要方法非常简短,这样它只需缠绕手表并开始运行,可以这么说。
  4. 格式化的代码很难阅读。 请考虑编辑您的post并修复缩进样式,使其统一且一致。 我通常避免使用制表符进行缩进(论坛软件通常不能很好地使用制表符)并缩进每个代码块4个空格。
  5. 你几乎不想让你的类扩展Thread。 相反,让它实现Runnable(或使用Rod_Algonquin的出色推荐)。
  6. 不要使用弃用的方法,如DataInputStream#readLine(...)因为这可能很危险。

例如,你的主要可以像这样简单……

 public static void main(String[] args) { MyServer myServer = new MyServer(); myServer.getThingsRunning(); } 

编辑
注意添加为警告:我通常不使用套接字,服务器套件或创建聊天程序,我仍然是使用Executors的新手,但你可以按照这些方式构建代码……

 public class MultiServer implements Runnable { public static final int PORT_NUMBER = 2222; private static final int THREAD_POOL_COUNT = 20; private List clientList = new ArrayList<>(); private ServerSocket serverSocket; private ExecutorService clientExecutor = Executors.newFixedThreadPool(THREAD_POOL_COUNT); public MultiServer() throws IOException { serverSocket = new ServerSocket(PORT_NUMBER); } @Override public void run() { // embed your socket acceptance loop in a Runnable's run method while (true) { try { Socket clientSocket = serverSocket.accept(); MultiClient client = new MultiClient(clientSocket); clientList.add(client); clientExecutor.execute(client); } catch (IOException e) { // TODO notify someone of problem! e.printStackTrace(); } } } // ..... more methods and such public static void main(String[] args) { try { MultiServer multiServer = new MultiServer(); new Thread(multiServer).start(); } catch (IOException e) { e.printStackTrace(); } } }