Reputation: 55
I am new to Threads. I am trying to broadcast message from the server to clients.but I cannot. It seems like the server is always listen to a new connection.But I can send messages to other clients using the clients terminal. My question is how to allow input while listening at the same time. Here is the code.
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<portNumber> "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 < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this) {
threads[i].os.println("*** A new user " + name
+ " entered the chat room !!! ***");
}
}
}
while (true) {
String line = is.readLine();
if (line.startsWith("/quit")) {
break;
}
if (line.startsWith("@")) {
String[] words = line.split("\\s", 2);
if (words.length > 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("<" + name + "> "
+ 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("<" + name + "> " + 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) {
}
}
}
Upvotes: 1
Views: 2230
Reputation: 285430
while (true)
loop.DataInputStream#readLine(...)
as this could be dangerous to do.For example, your main could be as simple as this...
public static void main(String[] args) {
MyServer myServer = new MyServer();
myServer.getThingsRunning();
}
Edit
Note added as a warning: I don't generally work with sockets, serversockets, or create chat programs, and I'm still new at using Executors, but you could structure your code something along these lines...
public class MultiServer implements Runnable {
public static final int PORT_NUMBER = 2222;
private static final int THREAD_POOL_COUNT = 20;
private List<MultiClient> 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();
}
}
}
Upvotes: 4