readUTF()
, хорошо, читает строку UTF.Он не возвращается, пока не прочитает один.Вот почему вы хотите читать с разных клиентов параллельно, поэтому не имеет значения, кто из них отправляет сообщение первым, оно будет прочитано и впоследствии может быть переслано независимо от других.Один из способов сделать это - запустить отдельный поток чтения для каждого клиента.
Вот простой сервер чата (я не хотел заниматься выбором клиентов, извините):
public class ChatServer {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(5555);
List<DataOutputStream> doss = new ArrayList<>();
while (true) {
Socket client = server.accept();
synchronized(doss) {
doss.add(new DataOutputStream(client.getOutputStream()));
}
new Thread(new Runnable() {
public void run() {
try (DataInputStream dis = new DataInputStream(client.getInputStream())) {
while (true) { // <--------- per-client loop
String message=dis.readUTF();
synchronized (doss) {
for (DataOutputStream dos : doss)
dos.writeUTF(message);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
}
}
Он имеетцентральное хранилище исходящих потоков (doss
) и один поток на клиент для чтения входящих потоков.Затем потоки читают строку из своего клиента и перенаправляют ее во все исходящие потоки навсегда (внутренний цикл while(true)
).
На стороне клиента циклы практически однострочные, один для чтения сообщения и отправкиэто на сервер, а другой для получения чего-то с сервера и печати на экране:
public class ChatClient {
public static void main(String[] args) throws Exception {
Scanner s = new Scanner(System.in);
System.out.print("Enter your nick: ");
String name = s.nextLine();
Socket socket = new Socket("localhost", 5555);
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
new Thread(new Runnable() {
public void run() {
try {
while (true) // <------- receiver loop, in thread
System.out.println(dis.readUTF());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
dos.writeUTF(name + " has joined the conversation");
while (true) // <------- sender loop
dos.writeUTF(name + ": " + s.nextLine());
}
}
Эта штука работает с жестко закодированным localhost
на порту 5555
, не обрабатывает ошибки привсе (сервер умирает, когда клиент уходит).Это должно было быть коротким.