Cannot communicate back to server from client - java

Here is my Server class, along with Admin/Client... The admin can recieve the initial message from the server, but cannot respond back to the server. The Server Socket is created, and when the admin connects to the Server, The Server's message is recieved and printed. Although once the Server's menu printout("1. Login, etc..."). I cannot enter an option via the console. It seems to be in a deadlock as soon as the admin prints out the menu sent from the server.
/**
A server that executes the Simple Bank Access Protocol.
*/
public class BankServer extends Thread {
private Socket sAdmin;
private Scanner inServer;
private PrintWriter outServer;
public static void main(String[] args) throws IOException {
Bank bank = new Bank(10);
ServerSocket server = new ServerSocket(8888);
System.out.println("Waiting for clients to connect...");
Thread admin = new BankServer();
admin.start();
while (true) {
Socket s = server.accept();
System.out.println("Client connected.");
BankService service = new BankService(s, bank);
Thread t = new Thread(service);
t.start();
}
}
#SuppressWarnings("resource")
public void run() {
try {
ServerSocket server = new ServerSocket(8889);
try {
System.out.println("Waiting for admin to connect...");
while (true) {
sAdmin = server.accept();
System.out.println("Admin connected.");
InputStream instream = sAdmin.getInputStream();
OutputStream outstream = sAdmin.getOutputStream();
inServer = new Scanner(instream);
outServer = new PrintWriter(outstream);
outServer.print(...+"1. Login\n"+etc...);
outServer.flush();
findCommand();
}
} finally {
sAdmin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void findCommand() throws IOException {
while (true) {
if (!inServer.hasNext()) {
return;
}
String command = inServer.next();
String chosenCommand;
switch (command) {
case "1":
chosenCommand = "LOGIN";
runCommand(chosenCommand);
break;
case "2":
etc...
}
}
}
...
}
Ive removed the runCommand method and some fields that don't cause problems to allow for an easier read.
Here is the the admin class. It will output the options sent from the server, but will not exit the loop of outputing the intial message, and allow me to enter a choice.
public class BankAdmin {
public static void main(String[] args) throws IOException {
Socket inAdmin = new Socket("localhost", 8889);
InputStream instream = inAdmin.getInputStream();
OutputStream outstream = inAdmin.getOutputStream();
Scanner in = new Scanner(instream);
PrintWriter adminOut = new PrintWriter(outstream);
Scanner console = new Scanner(System.in);
while (true) {
if (!in.hasNextLine()) {
String command = console.next();
System.out.println("Sending: " + command);
adminOut.print("command");
adminOut.flush();
} else {
String response = in.nextLine();
System.out.println(response);
}
}
}
}

This is what is happening:
After the server sends the menu to the client, the client becomes stuck in in.hasNextLine(). This is because the in.hasNextLine() will block (pause) for input, waiting for a new line (otherwise, it cannot determine whether there will be a next line). To fix this problem, you must use threads, with one waiting for input while the other reads from the console.
For more information, see the Javadoc on Scanner.hasNextLine()

Related

Java - How do I loop to read the InputStream until the user makes an input to continue?

I have a multithreaded client-server system which works back and forth with the client communicating first and the server replying.
However, for two specific clients, I need them to constantly check if there is data held in the input stream before proceeding when the user makes an input.
The program is a car park management system. When the car park is full(0 spaces available) and a car arrives at an entrance client, the system forms a queue of clients waiting to grant entry. When a car leaves the car park, the first client in the queue is removed and added to a BlockingQueue for that specific entrance client. I have created a direct output output stream for each of the entrance clients. So when a BlockingQueue is not empty, data is taken from this queue and output is sent to the stream of that specific client.
However, the problem is - the entrance client which was queued should automatically read its InputStream and print the data to grant access, but instead it causes an error and crashes. I think what is happening is that when the system first starts, the is the client is stuck waiting to read data which initially doesn't exist because it would require some sort of input at the first stage, causing an error.
How do I fix this so that the client reads and prints the input stream(whether it be specific data such as contains the word "queue") IF there is data available else to continue IF the user makes an input.
I hope this makes sense, I tried to make it as clear as possible.
Server class:
public class Server {
public static void main(String[] args) throws IOException {
//Create the shared objects in the global scope...
int groundFloor = 0; //SET TO 0 FOR TESTING
int firstFloor = 0;
SharedState SharedStateObject = new SharedState(groundFloor,firstFloor);
//Sets up the server socket on port 4444
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(4444);
System.out.println("Car Park Server started." + "\n");
}
catch (IOException e) {
System.err.println("Could not start server on specified port.");
System.exit(-1);
}
//Got to do this in the correct order with only four clients!
ServerThread GroundFloorEntrance = new ServerThread(serverSocket.accept(), "GroundFloorEntrance", SharedStateObject);
ServerThread FirstFloorEntrance = new ServerThread(serverSocket.accept(), "FirstFloorEntrance", SharedStateObject);
ServerThread GroundFloorExit1 = new ServerThread(serverSocket.accept(), "GroundFloorExit1", SharedStateObject);
ServerThread GroundFloorExit2 = new ServerThread(serverSocket.accept(), "GroundFloorExit2", SharedStateObject);
GroundFloorEntrance.start();
FirstFloorEntrance.start();
GroundFloorExit1.start();
GroundFloorExit2.start();
serverSocket.close();
//Loop for granting queued clients access
while(true)
{
BlockingQueue<String> queuedGroundAccess = SharedStateObject.getQueuedGround();
BlockingQueue<String> queuedFirstAccess = SharedStateObject.getQueuedFirst();
if(!queuedGroundAccess.isEmpty())
{
Socket clientSocket = GroundFloorEntrance.clientSocket();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
try
{
out.println(queuedGroundAccess.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!queuedFirstAccess.isEmpty())
{
Socket clientSocket = FirstFloorEntrance.clientSocket();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
try
{
out.println(queuedFirstAccess.take());
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
Client
public class GroundFloorEntrance {
#SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
// Set up the socket, in and out variables
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
int port = 4444;
String serverName = "localhost";
String clientID = "Ground Floor Entrance";
try {
clientSocket = new Socket(serverName, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: "+ port);
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer = null;
String fromUser = null;
System.out.println("Initialised " + clientID + " client and IO connections");
//I THINK THE ISSUE IN THE FOLLOWING STRUCTURE:
while (true) {
fromServer = in.readLine();
if(fromServer != null && fromServer.contains("Queue: "))
{
System.out.println(fromServer);
}
fromUser = stdIn.readLine();
if (fromUser != null) {
out.println(fromUser);
}
fromServer = in.readLine();
System.out.println(fromServer);
}
}
}
A problem is in this loop. When you write fromServer = in.readLine(); it stop execution of your program and waits for data to be entered from server.
while (true) {
fromServer = in.readLine();
if(fromServer != null && fromServer.contains("Queue: "))
{
System.out.println(fromServer);
}
fromUser = stdIn.readLine();
if (fromUser != null) {
out.println(fromUser);
}
fromServer = in.readLine();
System.out.println(fromServer);
}
What you can do with that? You should read data from server in another thread to prevent blocking main thread while waiting for data. Like that:
new Thread(new MyRunnable(fromServer)).start();
And MyRunnable will look like this:
public class MyRunnable implements Runnable {
private Scanner scanner;
public MyRunnable(Scanner scanner) {
this.scanner = scanner;
}
#Override
public void run() {
while (true) {
if (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
}
If you will have some questions, please ask.

How to give an automated response back when receiving a specific message from the client (Java, sockets)

I basically was trying to give a response back from my server if my client sends me the message "Hello mr server". However it doesn't.
Here is my code :
public class Server {
public static final int PORT = 6666;
public static void main(String[] args) throws IOException {
new Server().runServer();
}
public void runServer() throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up and ready for connections.....");
while (true) {
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //for fetching data
String str = br.readLine(); //for fetching data
System.out.println("Client Data:" + str + '\n');
String dataSendingToClient = "gg";
OutputStreamWriter os = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out = new PrintWriter(os); //for sending data
out.println(dataSendingToClient);
os.flush();
if (br.equals("hey mr server")){
OutputStreamWriter os2 = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out2 = new PrintWriter(os); //for sending data
out2.println("hey mr client");
os.flush();
}
}
}
}
You are using br.equals("hey mr server") which will always return false, since br is not a String, but a BufferedReader
Instead you should use your already defined str variable str.equals("hey mr server")
Also note that with your current code, your server will only read one message from the client before moving on to the next connection
If you want your server to read more messages from a single client, you will need to loop until the client sends a disconnect message/the socket closes
while(true)
{
Socket socket = serverSocket.accept();
BufferedReader br = [...];
PrintWriter out = [...];
for(String message = br.readLine(); message != null; message = br.readLine())
{
//do stuff
//message is each line from the client
}
}
If you have multiple clients trying to connect, you will need to multithread the connections
I would recommend a class to enclose the connection details and use Stacks to poll if the client sent data
public static void main(String[] args) //or whatever other method you're running in
{
List<Connection> clients = new ArrayList<Connection>(); //some data structure to hold the clients
//start accepting connections
new Thread(new Runnable()
{
public void run()
{
while(true)
Connection client = new Connection(serverSocket.accept());
}
}).start();
//do something with the clients, read/write/whatever
}
private class Connection extends Runnable
{
private BufferedReader reader;
private PrintWriter writer;
private Queue<String> messages;
public Connection(Socket s)
{
reader = [...];
writer = [...];
messages = new LinkedList<String>();
}
public void run()
{
//just keep reading
while(true)
messages.add(reader.readLine();
}
public String read()
{
messages.poll();
}
public void write(String msg)
{
writer.write(msg);
writer.flush();
}
}
Note: take that as rough pseudocode

Modifying a server to allow multiple clients to connect concurrently

So I've created a server and a client for a previous part of the assignment, but now I have to extend/modify the server so that it can handle multiple clients concurrently.
I know I have to do something along the lines of
Server server1 = new Server();
Thread thread = new Thread(server1);
thread.start();
and have the Class Server implement Runnable.
But the lecturers notes on multi-threading are not very clear and I have been starring at this part of the question for a long time and have got no where.
Below is the code I have written for one client at a time to connect to the server.
Any help would be much appreciated.
Server.java
public class Server {
ArrayList<String> tokens = new ArrayList<String>();
private Socket s;
private Scanner in;
private PrintWriter out;
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(1234);
Server serverInstance = new Server();
System.out.println("Server running. Waiting for a client to connect...");
while (true) {
serverInstance.s = server.accept();
System.out.println("Client connected");
serverInstance.run();
System.out.println("Client disconnected. Waiting for a new client to connect...");
}
}
public void start() {
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread(this, threadName);
t.start();
}
}
public void run() {
try {
try {
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
doService(); // the actual service
}
finally {
s.close();
}
}
catch (IOException e) {
System.err.println(e);
}
}
public void doService() throws IOException {
while (true) {
if (!in.hasNext())
return;
String request = in.next();
System.out.println("Request received: " + request);
// (...) test for type of request here (not implemented)
Request(request);
}
}
public void Request(String request) {
String amountStr = in.next();
if (request.startsWith("SUBMIT")) {
if (tokens.size() < 10) {
tokens.add(amountStr);
System.out.println("Token added");
out.println("OK");
}
else {
System.err.println("Error");
out.println("Error");
}
}
else if (request.startsWith("REMOVE")) {
if (tokens.contains(amountStr)) {
tokens.remove(amountStr);
System.out.println("Tokens removed");
out.println("OK");
}
else {
System.err.println("Error");
out.println("Error");
}
}
else if (request.equals("QUIT")) {
System.err.println("Program ended");
out.println("Program ended");
}
tokens.sort(null);
System.out.println(tokens);
out.flush();
}
}
Client.java
public class Client {
public static void main(String[] args) throws IOException {
Socket s = new Socket("localhost", 1234);
InputStream instream = s.getInputStream();
OutputStream outstream = s.getOutputStream();
Scanner in = new Scanner(instream);
PrintWriter out = new PrintWriter(outstream);
String request = "SUBMIT hello \n";
out.print(request);
out.flush();
String response = in.nextLine();
System.out.println("Token: " + response);
s.close();
}
}
What you are trying to duplicate is what RMI has been doing for decades. Java is open source so you can look at how RMI works and learn from there. You can also look on the internet for myriad examples of multi threaded servers with/without RMI.

User input does not work within a java thread. What am I doing wrong?

Ok, I am trying to make a simple chat server and client. This program is the chat server.
I have two threads that are running. The first thread handles all of the clients and binds each new client to a new socket using ServerSocket and the second thread for now allows the user to send a message to the connected client. I cannot, however, get user input from within this thread! The statement "String inputvar = br.readLine()" will not execute! What am I doing wrong?
public void relay() throws IOException
{
new Thread(new Runnable()
{
#Override
public void run()
{
try{
try
{
while (true)
{
Socket socket2 = null;
Socket socket1 = socketmethod(socket2,0);
System.out.println(socket1);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (socket1 != null)
{
PrintWriter outputriver = new PrintWriter(socket.getOutputStream(),true);
boolean cfd = true;
while(cfd==true)
{
System.out.println("this worked");
System.out.print("Message: ");
String inputvar = br.readLine();
System.out.println("this worked2");
if (inputvar.equals("disconnect_now"))
{
cfd = false;
}
outputriver.println("Unknown User: " + inputvar);
}
}
}
}
finally
{
System.out.println("error 1");
}
}
catch (IOException e)
{
System.out.println("Unexpected error: IOException in thread2");
}
}
}).start();
I can't tell from your code where you are initiating accepting your client connection. I would expect to see something like this...
public void replay() {
try {
serverSocket = new ServerSocket(port);
while(true) {
try {
final Socket connection = serverSocket.accept();
new Thread(new Runnable() {
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String value = br.readLine();
PrintWriter pw = new PrintWriter(connection.getOutputStream(), true);
pw.println(value);
However if you are accepting multiple client requests having many threads, you will have them block on br.readline() as they compete for System.in
Also make sure that your input is sending the correct "new line" character(s) in order to fulfill the readline() requirements.

Why isn't my server Reacting to input until after I disconnect?

I have a simple Server-Multi Client program that sends input from a user out to everyone.
The Server gets messages, and then sends them systematically out to everyone.
The problem I'm having is that the server gets the messages, but doesn't send them back until I disconnect from the server. I have one thread for each user, and one thread that sends out the messages.
Here is the Main server:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(25566);
SendThread SendThread = new SendThread();
new Thread(SendThread).start();
while(true){
Socket clientSocket = serverSocket.accept();
CollectThreads socketThread = new CollectThreads(clientSocket);
SendThread.Clients.add(socketThread);
new Thread(socketThread).start();
}
}
Here is the Input Thread(CollectThreads):
public Socket Client;
public CollectThreads(Socket socket)
{
//Here we set the socket to a local variable so we can use it later
Client = socket;
}
#Override
public void run() {
System.out.println("i");
try{
PrintWriter out = new PrintWriter(Client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(Client.getInputStream()));
out.println("Connected");
boolean x = true;
while(x){
String s;
if((s = in.readLine()) != null){
System.out.println(s);
SendThread.log.add(s);
}
}
} catch(IOException exception) {
System.out.println("Error: " + exception);
}
}
And the Sender(SendThread):
public ArrayList<CollectThreads> Clients = new ArrayList<CollectThreads>();
public static ArrayList<String> log = new ArrayList<String>();
#Override
public void run() {
try{
while(true){
String x;
while(!Clients.isEmpty()){
x = log.get(0);
for(int c = 0; c < Clients.size(); c += 1){
PrintWriter out = new PrintWriter(Clients.get(c).Client.getOutputStream(), true);
out.println(x);
System.out.println(x);
}
log.remove(0);
}
}
} catch(IOException exception) {
System.out.println("Error: " + exception);
}
}
If I input x, The server console prints x, I disconnect, and then it prints x the second time.
Can anyone find my mistake? or tell me why this isn't working?
You're never removing anything from SendThread.Clients, so I can't see why it won't just keep resending the same thing indefinitely.
It's a very strange design. Why not have each client thread send its own output, like everybody else?

Categories