So I have a program that clients can enter any type of tasks and other clients can check it as well but I don't know how to close the loop that tries to accept new connetions to the server.
What I want is when I close the last client running using a command I wrote I want the server to close as well.
Can anyone help?
public class TaskListServer {
public static List<String> taskList = new ArrayList<>();
public static String uniqueString(){
return String.join(", ", taskList);
}
public static void addTasks(String task) {
taskList.add(task);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
try {
ServerSocket serverSocket = new ServerSocket(4242);
while (true) {
Socket clientSocket = serverSocket.accept();
ThreadedServer clientThread = new ThreadedServer(clientSocket);
new Thread(clientThread).start();
}
}catch (IOException e) {
e.printStackTrace();
}
sc.close();
}
Don't use an infinity loop (while(true)).
private static boolean acceptNewClients = true;
public static void flipAcceptNewClients() {
acceptNewClients = !acceptNewClients;
}
public static void main(String[] args) {
/* your code here */
while (acceptNewClients) {
Socket clientSocket = serverSocket.accept();
ThreadedServer clientThread = new ThreadedServer(clientSocket);
new Thread(clientThread).start();
}
/* your code here */
}
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();
}
}
I try to disconnect my client:
public class SiecZapis {
public static Socket gniazdo2;
public static void main(String[] args) {
new SiecZapis().doIt2();
}
public void doIt2() {
try {
ServerSocket gniazdo = new ServerSocket(4242);
while(true) {
Socket gniazdo2 = gniazdo.accept();
PrintWriter pisarz = new PrintWriter(gniazdo2.getOutputStream());
String porada = "test2";
pisarz.println(porada);
pisarz.close();
System.out.println(porada);
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
public void exit() {
gniazdo2.disconnect();
}
}
I tried to use something like socket.disconnect() from this topic but there is not method disconnect in socket.
Could you please advise how to handle this topic?
Insted of disconnect try using the close method.
public void exit(){
gniazdo2.close();
}
Further reading: https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#close--
I have made Client.java and Server.java. Here they are below.
Client
public class Client
{
ClientConnection cc;
public static void main(String[] args)
{
new Client();
}
public Client()
{
try
{
Socket s = new Socket("localhost",4444);
cc = new ClientConnection(s,this);
cc.start();
listenForInput();
} catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
public void listenForInput(){
Scanner console = new Scanner(System.in);
while(true){
while(!console.hasNextLine()){
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
String input = console.nextLine();
cc.sendStringToServer(input);
}
}
}
Server
public class Server
{
ServerSocket ss;
ArrayList<ServerConnection> connections = new ArrayList<ServerConnection>();
boolean shouldRun = true;
ServerWindow serverWindow;
public static void main(String[] args)
{
new Server();
}
public Server(){
try
{
serverWindow= new ServerWindow();
serverWindow.setVisible(true);
ss = new ServerSocket(4444);
serverWindow.serverLog("Server starting");
while(shouldRun){
Socket s = ss.accept();
ServerConnection sc = new ServerConnection(s,this);
sc.start();
connections.add(sc);
serverWindow.serverLog("A client connected from " + sc.getIP());
}
} catch (IOException e)
{
e.printStackTrace();
}
}
public ServerWindow getServerWindow(){
return serverWindow;
}
}
When i run Client.java and Server.java they connect fine and carry out their tasks as expected. But when I am in a new class and i create a client object and a server object, the client doesnt work properly.
public class tester
{
public static void main(String[] args)
{
Server server = new Server();
Client client = new Client();
client.cc.sendStringToServer("From tester");
}
}
The server works fine, it creates the window as expected but the client object doesnt work. My server object will not recognize a connection like it does when it normally works and my client's message will not go through. What am I missing? Does it have to do with using localhost as the ip?
Your problem is that you block the main thread by calling
listenForInput();
in your Client. Create a new Thread that calls the input listener and you will be fine.
new Thread(new Runnable() {
public void run() {
listenForInput();
}
}).start();
Edit: The same problem is in the Server class. There is an infinite loop, that blocks the Server constructor from finishing. Also add this:
new Thread(new Runnable() {
public void run() {
while(shouldRun) {
Socket s = ss.accept();
// do other stuff
}
}
}).start();
Note: You do not need to sleep the thread when waiting for input. Just write some empty brackets or a semicolon.
while (!console.hasNextLine()) ;
I have a class that implements Runnable, and I start it's own thread in another method that runs when the window opens, however the while loop I have in the Runnable method only runs once, I know this because it displays the output only once. This is the code below.
static private final int SOCKET = 2222;
static JFrame frame = new JFrame();
static private ServerSocket serverSocket;
static private Socket socket;
static private DataOutputStream out;
static private DataInputStream in;
static private ArrayList<User> users = new ArrayList<>();
static private int logged = -1;
public GameServer() {
initComponents();
}
public void runServer() {
Thread server = new Thread(new StartServer());
server.start();
}
public void addUser(int logged, Socket socket, JTextArea taOut) {
users.add(logged, new User(socket, taOut, this, logged));
Thread thread = new Thread(users.get(logged));
thread.start();
}
public void removeUser(int index, Socket socket) {
users.remove(index);
updateIndexes();
try {
socket.close();
} catch (Exception e) {
taOut.append("Failed to close connection to user.\n");
}
}
public void updateIndexes() {
for (int i = 0; i == users.size()+1; i++) users.get(i).lowerIndex();
logged--;
}
public class StartServer implements Runnable {
#Override
public void run() {
taOut.append("Attempting to start server.\n");
try {
serverSocket = new ServerSocket(SOCKET);
} catch (Exception e) {
taOut.append("Port "+SOCKET+" is in use.\n");
return; // Prevent any further code from executing
}
taOut.append("Server started successfully.\n");
while (true) {
try {
taOut.append("Waiting for user...\n");
socket = serverSocket.accept(); // Wait for user to connect
logged++;
addUser(logged, socket, taOut);
taOut.append("Login request from: "+socket.getInetAddress()+"\n");
} catch (Exception e) {
taOut.append("There was an error with a user trying to connect.\n");
}
break;
}
}
}
private void formWindowOpened(java.awt.event.WindowEvent evt) {
runServer();
}
The body of the loop ends with a break; that terminates the loop. Just remove it and you should be fine.
I'm trying to figure out a way to get an instance of a server to negotiate between two clients by creating a chat thread between them.
I created this project, and it "almost" works... but it seems like there is a buffer of synch problem.
when writing a line in one side (i.e Client#1), it doesn't pass to the other side (i.e Client#2), but only after Client#2 trys to pass a line too.
I know there might be better ways to implement this, but I'd like to understand what's wrong with my code.
your help would be great!
the code:
server
import java.io.*;
import java.net.*;
public class Server
{
public static void main(String[] args)
{
int id = 1;
System.out.println();
System.out.println("Server");
try
{
ServerSocket serverSocket = new ServerSocket(4321);
while (true)
{
Socket client1Socket = serverSocket.accept();
Socket client2Socket = serverSocket.accept();
System.out.println("clients connected from ports: \n"
+ client1Socket.getPort() + ", " + client2Socket.getPort());
Thread client1Thread = new ServerThread(client1Socket, client2Socket, id);
client1Thread.start();
id++;
Thread client2Thread = new ServerThread(client2Socket, client1Socket, id);
client2Thread.start();
id++;
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
server thread
import java.io.*;
import java.net.*;
import java.util.*;
public class ServerThread extends Thread
{
Socket sourceSocket;
Socket destSocket;
int id;
public ServerThread(Socket src, Socket dst, int n)
{
sourceSocket = src;
destSocket = dst;
id = n;
}
public void run()
{
try
{
Scanner clientInput = new Scanner(sourceSocket.getInputStream());
PrintStream destOutput = new PrintStream(destSocket.getOutputStream());
destOutput.println("You are chatting with Client " + id);
boolean more = true;
while (more)
{
String input = clientInput.nextLine();
destOutput.println(input);
if (input.equals("Q"))
{
more = false;
}
}
sourceSocket.close();
destSocket.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
client
import java.io.*;
import java.net.*;
import java.util.*;
public class Client
{
public static void main(String[] args)
{
System.out.println();
System.out.println("Client");
try
{
Socket clientSocket = new Socket("localhost", 4321);
System.out.println("Connection Established");
Scanner input = new Scanner(clientSocket.getInputStream());
PrintStream output = new PrintStream(clientSocket.getOutputStream());
Scanner in = new Scanner(System.in);
System.out.println(input.nextLine());
boolean more = true;
while (more)
{
String text = in.nextLine();
output.println(text);
String nextInput = input.nextLine();
if (nextInput == null)
{
more = false;
}
else
{
System.out.println(nextInput);
}
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
In your client code, the line String text = in.nextLine(); will block your thread. That means if you never type in anything in your client, you can not receive anything. So the solution is to put your message receiving code in another thread. such as:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (!Thread.interrupted()) {
System.out.println(input.nextLine());
}
}
});
thread.start();
while (true)
{
String text = in.nextLine();
output.println(text);
// String nextInput = input.nextLine();
......................
}