I have a project in which i make a chat server, where people(client) connect and choose a partner to chat with. However, they chat only when both clients send a message they see what the other typed. What I want is something like Whatsapp where we send many messages one after the other without waiting for the other client to send.
I tried to create a thread class where I invoke the chat and other stuff, but never worked.
//this is the client.java and this is the part of the code where they start chatting
do {
System.out.print(dis.readUTF());
System.out.println(dis.readUTF());
send = in.next();
dos.writeUTF(send);
b = dis.readBoolean();
} while (b);
//this is part of the chatserver.java where the connection is done they start chatting
class handleClient implements Runnable {
private Socket s1;
private Socket s2;
private String name1;
private String name2;
public handleClient(Socket s1, Socket s2, String n1, String n2) {
this.s1 = s1;
this.s2 = s2;
this.name1 = n1;
this.name2 = n2;
}
@Override
public void run() {
String msg1 = "", msg2 = "";
boolean b;
try {
DataOutputStream dos1 = new DataOutputStream(s1.getOutputStream());
DataInputStream dis1 = new DataInputStream(s1.getInputStream());
DataOutputStream dos2 = new DataOutputStream(s2.getOutputStream());
DataInputStream dis2 = new DataInputStream(s2.getInputStream());
do {
dos1.writeUTF(name1 + ": ");
dos2.writeUTF(name2 + ": ");
dos2.writeUTF(name1 + ": " + msg1);
msg1 = dis1.readUTF();
dos1.writeUTF(name2 + ": " + msg2);
msg2 = dis2.readUTF();
b = !msg1.equals(name1 + " is out") && !msg2.equals(name2 + " is out");
dos1.writeBoolean(b);
dos2.writeBoolean(b);
} while (b);
dos1.close();
dis1.close();
dos2.close();
dis2.close();
s1.close();
s2.close();
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
}
readUTF()
, well, reads an UTF string. It does not return until it has read one. That is why you want to read from the different clients in parallel, so it would not matter which one sends a message first, it would be read and could be forwarded afterwards, independently from others. One way to do that is starting a separate reader thread for each client.
Here is a simple chatroom server (I did not want to deal with selecting clients, sorry):
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();
}
}
}
It has a central storage of outgoing streams (doss
), and one thread per client for reading the inbound streams. Then the threads read a string from their client and forward it to all of the outgoing streams, forever (the inner while(true)
loop).
On the client side the loops are practically one-liners, one for reading message and sending it to the server, and an other one for getting something from the server and printing it on the screen:
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());
}
}
The thing works with hardcoded localhost
on port 5555
, provides no error handling at all (server dies when a client leaves). It was meant to be short.