Nishant Agarwal Nishant Agarwal - 2 months ago 6
Java Question

Java: Sending data from a server to all clients listening on the socket

I have created a quizServer application in java swing that connects to multiple clients through a socket. I am able to send data to the server from each client simultaneously through the socket connection but when I try to send data to the clients from the server then it is being received by only 1 client. How can I modify the code to send data to all the clients listening on the socket at the same time? Any code/pseudo-code will be appreciated.

This is my NetworkClient class:

public class NetworkClient {

PrintWriter os = null;
Socket s1 = null;
String line = null;
BufferedReader br = null;
BufferedReader is = null;
InetAddress address = null;

void initClient() {
try {
address = InetAddress.getLocalHost();
System.out.println(address);
} catch (UnknownHostException ex) {
Logger.getLogger(NetworkClient.class.getName()).log(Level.SEVERE, null, ex);
}

try {
s1 = new Socket(address, 8888); // You can use static final constant PORT_NUM
br = new BufferedReader(new InputStreamReader(System.in));
is = new BufferedReader(new InputStreamReader(s1.getInputStream()));
os = new PrintWriter(s1.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
System.err.print("IO Exception");

}
}

void sendVal(int data) {
os.println(data);
os.flush();
}

void close() {
try {
is.close();
os.close();
br.close();
s1.close();
} catch (Exception ex) {
Logger.getLogger(NetworkClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}


Here is my Server class:

public class QuizServer {

QuizJFrame frame;
ServerThread st;

void initServer(QuizJFrame frm) {

frame = frm;
Socket s = null;
ServerSocket ss2 = null;
System.out.println("Server Listening......");
try {
ss2 = new ServerSocket(8888); // port number used as 8888

} catch (IOException e) {
e.printStackTrace();
System.out.println("Server error");
}

while (true) {
try {
s = ss2.accept();
System.out.println("connection Established");
st = new ServerThread(s, frm);
st.start();

} catch (Exception e) {
e.printStackTrace();
System.out.println("Connection Error");

}
}
}
}


This is the server thread class:

class ServerThread extends Thread {

BufferedReader is = null;
PrintWriter os = null;
Socket s = null;
QuizJFrame frame;
String question[] = {"", "QUESTION 1", "QUESTION 2", "QUESTION 3", "QUESTION 4", "END"};
int answer[] = {0, 1, 2, 3, 4};
int index;

public ServerThread(Socket s, QuizJFrame frm) {
this.s = s;
frame = frm;
index = 1;
frame.setQuestion(question[index]);
}

@Override
public void run() {
int option = 0;
try {
is = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = new PrintWriter(s.getOutputStream());

} catch (IOException e) {
System.out.println("IO error in server thread:" + e);
}
try {
while (option > -1) {
try {
option = Integer.parseInt(is.readLine());
os.println(answer[index] == option);
os.flush();
} catch (NumberFormatException e) { //to handle null value
}
System.out.println(result(option));
frame.output(result(option));
}
} catch (IOException ex) {
Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}

}

String result(int op) {
if (op == -1) {
return "Client exited";
}
if (answer[index] == op) {
return "Option " + op + " is the correct answer.";
} else {
return "Option " + op + " is incorrect.";
}
}

void nextQues() {
index++;
frame.setQuestion(question[index]);
os.println(-2);
os.flush();
}
}


EDIT : Using
List<ServerThread>
resolved the issue.

Answer

Your server has only one ServerThread variable, and thus can only send data to one socket, the last one added. Instead, consider giving the class an List<ServerThread> variable to allow it to communicate with all the clients. Then in the while loop where you create connections, add each newly created ServerThread to this list.

You'll also need to fix your server's threading issues so that the while (true) loop doesn't block key code.

You'll also need to upgrade the ServerThread class so that the main server object can communicate with its streams.

Also you almost never want to have a class extend Thread. Have it implement Runnable instead.