I have a socket that is consuming 100% of the computer's CPU.
There are 150 clients sending messages to the server every 30 seconds unsynchronously.
Does anyone know how to solve this problem?
Below is my ServerSocket class
public class Servidor {
static ExecutorService es;
public static void main(String[] args) throws Exception {
es = Executors.newFixedThreadPool(150);
ServerSocket servidor = new ServerSocket(2010);
while (true) {
Socket soquete = null;
try {
System.out.println("Aguardando cliente: ");
soquete = servidor.accept();
System.out.println("Cliente Conectado: ");
es.execute(new Conexao(soquete));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The Conexao class (utility class) takes the string sent by the clients and saves it in the database.
Below my Conexao class
public class Conexao implements Runnable{
Socket soquete;
int contador = 0;
public Conexao(Socket soquete) {
super();
this.soquete = soquete;
}
#Override
public void run(){
BufferedReader in = null;
try{
in = new BufferedReader(new InputStreamReader(soquete.getInputStream()));
while (!in.ready()) {/*System.out.println("!in.ready()");*/}
String str =in.readLine();
System.out.println("Rodando Thread"+Thread.currentThread().getName() + " : texto: " + str);
}finally{
...
if(soquete != null){
try {
soquete.close();
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
}
}
}
I solved the problem by removing part "while (!in.ready()) {/System.out.println("!in.ready()");/}" and creating a "Thread.sleep" at the end of the try block
Related
I am trying to create for a university project a server / slave / client project.
The server should open 2 ports, one port will be for the connection of the slave and another port for the client.
I have setup 2 threads 1 for the client and another for the slave. The client should sent random numbers to server and server should forward randomly those numbers to slave instances. The slave should check if the current number exist on their list and if it's not available to store it, otherwise they should sent a message to server that the number already exist.
Then I created the client thread which consist of 2 threads, one for sending the numbers to server and another thread to read messages coming from the server.
There is something wrong with the code of the PrintWriter, I cannot make it to send the numbers to server when the code is inside the thread. If I move the code on the main and cancel the thread the messages are being sent without any issue.
What could be the issue for this?
Below is the current code from server (master) and the client.
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1";
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
Socket echoSocket = null;
BufferedReader in = null;
try {
echoSocket = new Socket(serverHostname, 18889);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Δεν μπορεί να πραγματοποιηθεί σύνδεση με τον σέρβερ: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + serverHostname);
System.exit(1);
}
ClientOut clientOut = new ClientOut(echoSocket);
clientOut.start();
ClientIn clientIn = new ClientIn(in);
clientIn.start();
in.close();
echoSocket.close();
}
public static class ClientOut extends Thread {
private PrintWriter out;
public ClientOut(Socket echoSocket) throws IOException {
this.out = new PrintWriter(echoSocket.getOutputStream(), true);
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
out.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
out.close();
}
}
public static class ClientIn extends Thread {
private BufferedReader in;
public ClientIn(BufferedReader in) {
this.in = in;
}
#Override
public void run() {
}
}
}
public class Master {
private int slavePort;
private int clientPort;
private SlaveThread slaveThread;
private ClientThread clientThread;
private boolean running = false;
public static int slaveConnected; // Slave connection counter
public Master(int slavePort, int clientPort) {
this.slavePort = slavePort;
this.clientPort = clientPort;
this.slaveConnected = 0;
public void startServer() {
try {
this.slaveThread = new SlaveThread(slavePort);
this.clientThread = new ClientThread(clientPort);
System.out.println( "Αναμονή για σύνδεση client / slave" );
slaveThread.start();
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopServer() {
running = false;
this.slaveThread.interrupt();
this.clientThread.interrupt();
}
class SlaveThread extends Thread {
private ServerSocket slaveSocket;
SlaveThread(int slavePort) throws IOException {
this.slaveSocket = new ServerSocket(slavePort);
}
#Override
public void run() {
running = true;
while (running) {
try {
// Call accept() to receive the next connection
Socket slSocket = slaveSocket.accept();
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Slave");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ClientThread extends Thread {
private ServerSocket clientSocket;
ClientThread(int clientPort) throws IOException {
this.clientSocket = new ServerSocket(clientPort);
}
#Override
public void run() {
running = true;
while (running) {
try {
Socket clSocket = clientSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clSocket.getInputStream()));
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Client");
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Client: " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Master server = new Master( 30091, 18889);
server.startServer();
// Automatically shutdown in 1 minute
try {
Thread.sleep( 60000 );
} catch(Exception e) {
e.printStackTrace();
}
server.stopServer();
}
I found the solution.
The Socket should be created on the Client Thread constructor and not to be passed as reference.
So the client should be
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1"; //Ορίζουμε την διεύθυνση που είναι ο σέρβερ
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
ClientOut clientOut = new ClientOut(serverHostname);
clientOut.start();
ClientIn clientIn = new ClientIn(serverHostname);
clientIn.start();
}
public static class ClientOut extends Thread {
private Socket echoSocket;
private PrintWriter writer;
ClientOut(String serverHostname) throws IOException {
this.echoSocket = new Socket(serverHostname, 18889);
this.writer = new PrintWriter(echoSocket.getOutputStream(), true);;
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
writer.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
writer.close();
}
}
Explanation
I'm currently trying to create a Multiplayer Game with Java where up to five Players can play together.
The problem is that when I'm trying to connect multiple Clients to my Server I get an Exception and the Server doesn't work anymore.
With one Client at a time, everything works fine.
So what I need is a Server that can handle up to five players at a time and the clients should always get some new game data from the Server
every few seconds (Connected Players, etc.).
The "Game data" in the code below is the String I'm sending through the Object Stream.
Normally I would send an Object which has all the game data, but with the String, I get the same problem.
I'm struggling with the problem that only one Client can connect without any errors occurring for some days now and I didn't find a solution to my problem.
I saw that there are things like java.nio or the ExecutorService, but I didn't really understand those that much, so I don't know if they can help.
I have made a smaller program that simulates the same problem I get with my bigger program.
To Start the Server, you need to Start the GameMultiPlayerCreate.java Class, and for the Client, the Client.java class.
I'm new to Sockets so if something is unnecessary or if something can be made better please let me know.
So the Error I'm getting when I connect two or more Clients is:
java.io.StreamCorruptedException: invalid stream header: 00050131
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at Server.waitForData(Server.java:89) //I highlighted that in the code with a comment
at Server.loopWaitForData(Server.java:49)
at Server.run(Server.java:34)
at java.lang.Thread.run(Unknown Source)
Code
GameMultiPlayerCreate.java: Should start the Server threads if a Client connects
public class GameMultiPlayerCreate {
ServerSocket socketServer = null;
static String settingIp = "localhost";
static String settingPort = "22222";
static byte settingPlayers = 5;
public static int connectedPlayers = 0;
public static void main(String[] args) {
try {
GameMultiPlayerCreate objGameMultiPlayerCreate = new GameMultiPlayerCreate();
objGameMultiPlayerCreate.createServer();
} catch (NumberFormatException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
public void createServer() throws NumberFormatException, UnknownHostException, IOException, InterruptedException {
while (connectedPlayers < settingPlayers) {
socketServer = new ServerSocket(Integer.parseInt(settingPort), 8, InetAddress.getByName(settingIp));
System.out.println("Server is waiting for connection...");
Socket socket = socketServer.accept();
new Thread(new Server(socket)).start();
Thread.sleep(5000);
socketServer.close();
}
}
}
Server.java: This is the Class of which a new Thread should be created for each connected Client (Client Handler)
public class Server implements Runnable {
protected static Socket socket = null;
private int loops;
private int maxLoops = 10;
private int timeout = 10000;
protected static boolean killThread = false;
private boolean authenticated = true; //true for testing
protected static String ip;
protected static int port;
public Server(Socket socket) throws IOException {
Server.socket = socket;
}
public void run() {
try {
socket.setSoTimeout(timeout);
} catch (SocketException e) {
System.out.println("Error while trying to set Socket timeout. ");
System.out.println("Closing Thread..." + Thread.currentThread());
disconnectClient();
}
if (!killThread) {
GameMultiPlayerCreate.connectedPlayers = GameMultiPlayerCreate.connectedPlayers + 1;
loopWaitForData();
}
}
private void disconnectClient() {
System.out.println("Kicking Client... " + Thread.currentThread());
killThread = true;
GameMultiPlayerCreate.connectedPlayers = GameMultiPlayerCreate.connectedPlayers - 1;
}
public void loopWaitForData() {
while (!killThread) {
System.out.println(maxLoops + ", " + loops);
if (maxLoops - loops > 0) {
try {
waitForData();
} catch (SocketTimeoutException e) {
System.out.println("Error occurred while waiting for Data. Thread disconnected? Sending reminder. " + Thread.currentThread());
if (!authenticated) {
System.out.println("Kicking Client: Not authenticated");
disconnectClient();
} else {
commandReminder();
}
} catch (ClassNotFoundException | IOException e) {
loops = loops + 1;
System.out.println("Error occurred while waiting for Data. Waiting for more Data. " + Thread.currentThread());
e.printStackTrace();
loopWaitForData();
}
} else if (maxLoops - loops == 0) {
System.out.println("Error occurred while waiting for Data. Maximum trys reached. Disbanding connection. " + Thread.currentThread());
disconnectClient();
loops = loops + 1;
} else {
System.out.println("Closing Thread..." + Thread.currentThread());
disconnectClient();
}
}
}
private void commandReminder() {
System.out.println("Reminder");
try {
String code = new String("0");
ObjectOutputStream outputObject = new ObjectOutputStream(Server.socket.getOutputStream());
outputObject.writeObject(code);
} catch (IOException e) {
System.out.println("Error occurred while trying to authenticate Client: " + e + " in " + Thread.currentThread());
}
}
public void waitForData() throws IOException, ClassNotFoundException {
String code;
System.out.println("Waiting for Data...");
//Next line is where the error occurres
ObjectInputStream inputObject = new ObjectInputStream(socket.getInputStream());
while ((code = (String) inputObject.readObject()) != null) {
System.out.println("Received Data...");
System.out.println("Input received: " + code);
return;
}
}
}
Client.java: This is the Client
public class Client {
public static Socket socket = new Socket();
private int loops = 0;
private int maxLoops = 10;
private static boolean killThread = false;
private String ip;
private int port;
public Client(String receivedIp, String receivedPort) {
ip = receivedIp;
port = Integer.parseInt(receivedPort);
try {
System.out.println("Trying to connect to Server...");
socket.connect(new InetSocketAddress(ip, port));
System.out.println("Connected!");
} catch (IOException e) {
System.out.println("Error occurred while trying to connect to Server.");
}
loopWaitForData();
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Client objClient = new Client("localhost", "22222");
}
public void loopWaitForData() {
while (!killThread) {
System.out.println(maxLoops + ", " + loops);
if (maxLoops - loops > 0) {
try {
waitForData();
} catch (IOException | ClassNotFoundException e) {
loops = loops + 1;
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
}
System.out.println("Error occurred while waiting for Data. Waiting for more Data. " + Thread.currentThread());
e.printStackTrace();
loopWaitForData();
}
} else if (maxLoops - loops == 0){
System.out.println("Error occurred while waiting for Data. Maximum trys reached. Disbanding connection. " + Thread.currentThread());
try {
socket.close();
} catch (IOException e) {
System.out.println("Failed to close Socket " + Thread.currentThread());
}
loops = loops + 1;
} else {
System.out.println("Closing Thread..." + Thread.currentThread());
killThread = true;
}
}
}
public void waitForData() throws IOException, ClassNotFoundException {
InputStream input = socket.getInputStream();
ObjectInputStream inputObject = new ObjectInputStream(input);
String code;
System.out.println("Waiting for Data...");
while ((code = (String) inputObject.readObject()) != null) {
System.out.println("Received Data...");
System.out.println("Input received: " + code);
answer();
return;
}
}
private void answer() {
try {
String code = new String("1");
ObjectOutputStream outputObject = new ObjectOutputStream(socket.getOutputStream());
outputObject.writeObject(code);
} catch (IOException e) {
System.out.println("Error occurred while trying to answer: " + e + " in " + Thread.currentThread());
}
}
}
UPDATED
There is my updated code after the response,
I have one problem, now, i didn't receive anything :
Problem :
Connexion cliente reçue.
Lancement du traitement de la connexion cliente
Exception in thread "Thread-1" java.lang.NullPointerException
at cuisine.TimeServer.onResponseReceived(TimeServer.java:85)
at cuisine.ClientProcessor.run(ClientProcessor.java:43)
at java.base/java.lang.Thread.run(Thread.java:844)
TimeServer: 85 : Callback
#Override
public void onResponseReceived(String response) {
// When the response is received from ClientProcessor
// this method is called (by ClientProcessor).
// Your response is the parameter String response.
callback.onResponse(response);
}
Client processor: 43 :
server.onResponseReceived(response);
One client can connect but i can't receive anything : Json or text.
There is my new Java Code :
Main.java :
import cuisine.TimeServer.OnResponseReceivedListener;
public class main implements OnResponseReceivedListener {
public static void main(String[] args) throws IOException {
String host = "192.168.1.21";
int port = 8080;
TimeServer ts = new TimeServer(host, port);
ts.open();
System.out.println("------------Connected ! ------------");
}
#Override
public void onResponse(String response) {
doSomethingWith(response);
System.out.println("REPONSE : ");
System.out.println(response);
}
private void doSomethingWith(String response) {
System.out.println("REPONSE : ");
System.out.println(response);
}
}
I don't really know how to use the response now, because the sysout "RESPONSE" is not in my console
TimeServer.java :
...
import cuisine.ClientProcessor.Server;
public class TimeServer implements Server {
public interface OnResponseReceivedListener {
void onResponse(String response);
}
private int port = 2345;
private String host = "127.0.0.1";
private ServerSocket server = null;
private boolean isRunning = true;
private OnResponseReceivedListener callback;
public TimeServer() {
try {
server = new ServerSocket(port, 100, InetAddress.getByName(host));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public TimeServer(String pHost, int pPort) {
host = pHost;
port = pPort;
try {
server = new ServerSocket(port, 100, InetAddress.getByName(host));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void open() {
Thread t =
new Thread(
new Runnable() {
public void run() {
while (isRunning == true) {
try {
Socket client = server.accept();
System.out.println("Connexion cliente reçue.");
ClientProcessor c = new ClientProcessor(client);
Thread t = new Thread(c);
// Don't forget to define the Server for ClientProcessor
c.addServer(TimeServer.this);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
server = null;
}
}
});
t.start();
}
#Override
public void onResponseReceived(String response) {
// When the response is received from ClientProcessor
// this method is called (by ClientProcessor).
// Your response is the parameter String response.
callback.onResponse(response);
}
public void addOnResponseReceivedListener(OnResponseReceivedListener listener) {
callback = listener;
}
public void removeOnResponseReceivedListener() {
callback = null;
}
public void close() {
isRunning = false;
}
}
ClientProcessor.java :
public class ClientProcessor implements Runnable {
public interface Server {
void onResponseReceived(String response);
}
private Socket sock;
private PrintWriter writer = null;
private BufferedInputStream reader = null;
public List<Dish> dish;
// Your server instance
private Server server;
public ClientProcessor(Socket pSock) {
this.sock = pSock;
}
public void run() {
System.err.println("Lancement du traitement de la connexion cliente");
boolean closeConnexion = false;
while (!sock.isClosed()) {
try {
writer = new PrintWriter(sock.getOutputStream());
reader = new BufferedInputStream(sock.getInputStream());
String response = read();
// report the response to TimeServer
server.onResponseReceived(response);
InetSocketAddress remote = (InetSocketAddress) sock.getRemoteSocketAddress();
String debug = "";
debug = "Thread : " + Thread.currentThread().getName() + ". ";
debug += "Demande de l'adresse : " + remote.getAddress().getHostAddress() + ".";
debug += " Sur le port : " + remote.getPort() + ".\n";
debug += "\t -> Commande reçue : " + response + "\n";
System.err.println("\n" + debug);
String toSend = "";
switch (response.toUpperCase()) {
case "ORDER":
toSend = "Dish";
break;
case "CLOSE":
toSend = "Communication terminée";
closeConnexion = true;
break;
default:
toSend = "Commande inconnu !";
break;
}
writer.write(toSend);
writer.flush();
if (closeConnexion) {
System.err.println("COMMANDE CLOSE DETECTEE ! ");
writer = null;
reader = null;
sock.close();
break;
}
} catch (SocketException e) {
System.err.println("LA CONNEXION A ETE INTERROMPUE ! ");
break;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void addServer(Server server) {
this.server = server;
}
private void removeServer() {
server = null;
}
// La méthode que nous utilisons pour lire les réponses
private String read() throws IOException {
String response = "";
int stream;
byte[] b = new byte[4096];
stream = reader.read(b);
response = new String(b, 0, stream);
return response;
}
}
Thanks,
Benjamin.
Update (updated Main.java)
Update No2 (Removed static methods from Main.java and use a Main object)
Edit: (removed previous answer about sockets)
This is the json response, now i want to use it in my main : on
another class in the same package.
Since you've stated that you are getting a response from client but you don't know how to manipulate it in your Main class then your issue is not about sockets.
A solution: Use callbacks:
ClientProcessor will report the response to TimeServer.
TimeServer will report that response to Main.
Make ClientProcessor aware of the server and report when the response is fetched.
public class ClientProcessor implements Runnable {
public interface Server {
void onResponseReceived(String response);
}
private Socket sock;
private PrintWriter writer = null;
private BufferedInputStream reader = null;
public List<Dish> dish;
// Your server instance
private Server server;
public ClientProcessor(Socket pSock) {
this.sock = pSock;
}
public void run() {
System.err.println("Lancement du traitement de la connexion cliente");
boolean closeConnexion = false;
while (!sock.isClosed()) {
try {
writer = new PrintWriter(sock.getOutputStream());
reader = new BufferedInputStream(sock.getInputStream());
String response = read();
// report the response to TimeServer
server.onResponseReceived(response);
InetSocketAddress remote = (InetSocketAddress) sock.getRemoteSocketAddress();
String debug = "";
debug = "Thread : " + Thread.currentThread().getName() + ". ";
debug += "Demande de l'adresse : " + remote.getAddress().getHostAddress() + ".";
debug += " Sur le port : " + remote.getPort() + ".\n";
debug += "\t -> Commande reçue : " + response + "\n";
System.err.println("\n" + debug);
String toSend = "";
switch (response.toUpperCase()) {
case "ORDER":
toSend = "Dish";
break;
case "CLOSE":
toSend = "Communication terminée";
closeConnexion = true;
break;
default:
toSend = "Commande inconnu !";
break;
}
writer.write(toSend);
writer.flush();
if (closeConnexion) {
System.err.println("COMMANDE CLOSE DETECTEE ! ");
writer = null;
reader = null;
sock.close();
break;
}
} catch (SocketException e) {
System.err.println("LA CONNEXION A ETE INTERROMPUE ! ");
break;
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void addServer(Server server) {
this.server = server;
}
private void removeServer() {
server = null;
}
// La méthode que nous utilisons pour lire les réponses
private String read() throws IOException {
String response = "";
int stream;
byte[] b = new byte[4096];
stream = reader.read(b);
response = new String(b, 0, stream);
return response;
}
}
Now go to TimeServer and make it aware of Main (same procedure as before). You must also need to report the response to Main when its being received from ClientProcessor.
public class TimeServer implements Server {
public interface OnResponseReceivedListener {
void onResponse(String response);
}
private int port = 2345;
private String host = "127.0.0.1";
private ServerSocket server = null;
private boolean isRunning = true;
private OnResponseReceivedListener callback;
public TimeServer() {
try {
server = new ServerSocket(port, 100, InetAddress.getByName(host));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public TimeServer(String pHost, int pPort) {
host = pHost;
port = pPort;
try {
server = new ServerSocket(port, 100, InetAddress.getByName(host));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void open() {
Thread t =
new Thread(
new Runnable() {
public void run() {
while (isRunning == true) {
try {
Socket client = server.accept();
System.out.println("Connexion cliente reçue.");
Thread t = new Thread(new ClientProcessor(client));
// Don't forget to define the Server for ClientProcessor
t.addServer(TimeServer.this);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
server = null;
}
}
});
t.start();
}
#Override
public void onResponseReceived(String response) {
// When the response is received from ClientProcessor
// this method is called (by ClientProcessor).
// Your response is the parameter String response.
callback.onResponse(response);
}
public void addOnResponseReceivedListener(OnResponseReceivedListener listener) {
callback = listener;
}
public void removeOnResponseReceivedListener() {
callback = null;
}
public void close() {
isRunning = false;
}
}
Finaly, make your Main to listen to TimeServer and do something when it receives the response.
public class Main implements OnResponseReceivedListener {
public static void main(String[] args) {
Main application = new Main();
TimeServer ts = application.createTimeServer();
ts.addOnResponseReceivedListener(application);
ts.open();
System.out.println("------------Connected ! ------------");
}
#Override
public void onResponse(String response) {
doSomethingWith(response);
}
private void doSomethingWith(String response) {
// Your logic for the response here...
}
private TimeServer createTimeServer() {
String host = "192.168.43.178";
int port = 8080;
return new TimeServer(host, port);
}
}
I want to call a function cycle() that do something for every some x second.
At this time i can call it only when it has a request from client.
public class ChatServer implements Runnable {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
cycle();
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
out.println("NAMEACCEPTED");
writers.add(out);
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Yeah, code below is work when i remove Handle class from my code.
My problem is i can't combine them together, please help or suggest. Many thanks.
private void cycle() {
//do something
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
beforeTime = System.currentTimeMillis();
}
}
Do you try to start a separate thread for the cycle function before call listen to the socket.
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
//start separate thread to keep loop....
new Thread(new ChatServer()).start();
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
This is the simple client/server socket app for my faculty project. First, the Server class should be run, and then if Client class runs - it prints out the IP address of the local machine and the port that's been used.
I can't figure out one thing:
How and WHERE to create a method in class that will close(stop) the Server? And
how to make this like an event or something, for example if client
sends "stop" it should somehow stop the server...
SERVER.JAVA
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
System.out.println("The server has been summoned.\n");
System.out.println("The server is waiting for client to come...");
try {
ServerSocket servertest = new ServerSocket(2014);
while (true) {
try {
Socket ser = servertest.accept();
new ThreadSer(ser).start();
} catch (IOException e) {}
}
} catch (IOException e) {System.err.println(e);}
}
public static class ThreadSer extends Thread {
private Socket s;
public ThreadSer(Socket s) {
this.s = s;
}
#Override
public void run() {
try {
String response = "This is the IP: " + s.getLocalAddress() + " that has come via port: "
+ s.getLocalPort() + "\r\n";
OutputStream out = s.getOutputStream();
out.write(response.getBytes());
} catch (IOException e) { System.err.println(e); }
}}}
CLIENT.JAVA
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost", 2014);
new OutputThread(socket.getInputStream()).start();
}
public static class OutputThread extends Thread {
private InputStream inputstream;
public OutputThread(InputStream inputstream) {
this.inputstream = inputstream;
}
#Override
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(inputstream));
while (true) {
try {
String line = input.readLine();
System.out.println(line);
} catch (IOException exception) {
exception.printStackTrace();
break;
}
}
}}}
You should constantly ask for the inputstream of the client.. put it in the loop that always accept for the client input..
example:
public static class ThreadSer extends Thread {
private Socket s;
public ThreadSer(Socket s) {
this.s = s;
}
#Override
public void run() {
try {
String response = "This is the IP: " + s.getLocalAddress() + " that has come via port: "
+ s.getLocalPort() + "\r\n";
ObjectInputStream input = new ObjectInputStream(s.getInputStream());
while(true)
{
Object object = input.readObject();
if(object instanceof String)
{
String command = ((String) object).trim();
if(command.equals("stop"))
break;
}
}
s.close();
} catch (IOException e) { System.err.println(e); }
}}}