Server.java:
private Socket connection;
private int ID;
public static void main(String[] args) {
int port = 19999;
int count = 0;
try{
ServerSocket socket1 = new ServerSocket(port);
System.out.println("Server Initialized");
while (true) {
Socket connection = socket1.accept();
Runnable runnable = new Server(connection, ++count);
Thread thread = new Thread(runnable);
thread.start();
}
}
catch (Exception e) {}
}
Server(Socket s, int i) {
this.connection = s;
this.ID = i;//could use a client name as it is individual id for each thread.?
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
PrintWriter out = new PrintWriter(connection.getOutputStream(), true);
String inputLine;
while ((inputLine = in.readLine()) != null) {
Process p = new Process();
String output = p.input(inputLine);
out.println(output);
}
}
}
catch (Exception e) {
System.out.println(e);
}
finally {
try {
connection.close();
}
catch (IOException e){}
}
}
}
When run it creates a server, which when connected to by a client creates a thread for it so that it can handle multiple clients at one time.
However the code:
while ((inputLine = in.readLine()) != null) {
Process p = new Process();
String output = p.input(inputLine);
out.println(output);
}
loops the BufferedReader to get all the input given from the client. and when receives processes it and then sends the reply back to the client to be printed.
how can i get it so that i can send/get another question via the client at the same time as the first?
e.g
"user: hello computer how are you?"
"computer:I am good, how are you?"
"user: i am good"
"computer: that is nice to hear"
works fine. but:
"user: was is 1+1?"
"computer: 1+1=2"
"computer: any more question?"
"user: good?"
does not.
how can do it so that the server give multiple answers rather than having to wait for another input?
It would be easy to do if i set output as a string in server.java however every time i try to access the string to change it
(by using
Server s = new Server(); s.output = "stuff";) as the code suggests it just makes a new thread server. how can i access the already made thread?
You have to store the client thread into a kind of map and if you need to send a message to another thread, you could look up the map and get the reference to the other thread and send message from there.
Related
I have created this code snippet in both a single threaded version and multithreaded for a client/server setup I have going. I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
This is my first time trying to implement a multithreaded server and from my understanding it just a matter of putting in a client handler being
`
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
`
below is the snippet of the whole server code.
`
public class Server {
public static void main(String[] args) {
if (args.length < 1) return;
int port = Integer.parseInt(args[0]);
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
new ServerThread(socket).start();
}
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String text;
do {
text = reader.readLine(); // reads text from client
Process p = Runtime.getRuntime().exec(text);
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
String outputLine;
while ((outputLine = stdout.readLine()) != null) { // while serverMsg is not empty keep printing
writer.println(outputLine);
}
stdout.close();
writer.println("ENDCMD");
// Text here should just write back directly what the server is reading...?
}
while (!text.toLowerCase().equals("exit"));
socket.close();
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
`
I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
If you are not making a new connection for each command that you send, then this would be expected. Since each connection runs on one thread, a multi-threaded approach, as you have shown, would have the same speed as if you didn't make a new thread for each connection. The difference is that, without multi-threading, you can only have one connection at a time.
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.
i'm having trouble with the socket reading and writing through threads. The server's in erlang and the client in Java. The way i'm doing it is this:
PrintWriter printer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
TransmitterTwo trans = new TransmitterTwo(socket);
trans.start(); // Gets the message from socket
TransmitterTwo Class:
public class TransmitterTwo extends Thread {
Socket socket;
String message;
TransmitterTwo(Socket socket) {
this.socket = socket;
}
public String getMessageFromSocket() {
return message;
}
public void run() {
try {
String response = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((response = reader.readLine()) != null) {
System.out.println("Server response: "+ response);
this.message = response;
}
socket.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
The Problem is in the main client class. The idea is to: receive input from the console, send it to the socket, the server handles the logic and sends a response through the socket. Then on this client I check the response and do whatever i need to do. It's a registration flow, i register, i receive "register_ok", then i login...etc etc. The part of the loop where i'm having trouble is this:
while(true) {
String readerInput = reader.readLine(); // Read from console
printer.println(readerInput.trim()); // Sends it to the socket
while(trans.message == null);
socketMessage = trans.message;
Is this the right approach? The problem is that 'socketmessage' prints the previous received message, it's like..1 step behind, obviously this is thread related but I can't figure out the problem....help? Thanks
Your current approach is suboptimal because you're wasting your main thread spinning waiting on that variable to be updated. Because of how memory visibility works in java it may appear to never be updated (even if it actually is), or you may get stale values when you do access that variable. A more robust approach would be to pass messages between the threads using some of the built in collections in java:
public static void main(String[] args) {
// This queue will be the link between the threads where
// they can pass messages to each other
BlockingQueue<String> messages = new LinkedBlockingQueue<>();
PrintWriter printer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
TransmitterTwo trans = new TransmitterTwo(socket, queue);
trans.start(); // Gets the message from socket
...
while(true) {
String readerInput = reader.readLine(); // Read from console
printer.println(readerInput.trim()); // Sends it to the socket
// Wait for the other thread to push a message in to the queue.
String recv = messages.take();
}
}
public class TransmitterTwo extends Thread {
final Socket socket;
final BlockingQueue<String> queue;
TransmitterTwo(Socket socket, BlockingQueue<String> queue) {
this.socket = socket;
this.queue = queue;
}
public void run() {
try {
String response = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((response = reader.readLine()) != null) {
System.out.println("Server response: " + response);
// Add the response from the server to the queue
queue.add(response);
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This approach will never get stale values, and the take() operation on the main thread will block until there is some response from the server.
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.
So I did this client server program in java for my college mini project. Note that this is just a small module of a big project I'm working on. I need a string to be sent from the client to the server. The server will return back the string as it is back to the client. (The code will be modified later such that the string is processed before sending back). The client will send a string whenever needed to the server. Thus it means it is compulsory for the server to be running for indefinite time.
The problem I face here is that my server works perfectly only for the first time when the client sends a string. If I run the client the second time with a different string, I get back the same string I sent to the server previously!
Here is my server program:
public class Server {
public static boolean x = true;
public static String reply;
public static void main(String a[]) throws Exception {
System.out.println("Entered server console..");
Socket echoSocket = null;
ServerSocket serverSocket = null;
PrintWriter out = null;
BufferedReader in = null;
System.out.println("Initializing Connection..");
boolean runFlag = true;
try {
serverSocket = new ServerSocket(77);
while (runFlag) {
echoSocket = serverSocket.accept();
out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while (x) {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
reply = in.readLine();
if (reply != null) {
x = false;
}
}
System.out.println("received: " + reply);
out.println(reply);
System.out.println("sent back: " + reply);
stdIn.close();
}
} catch (Exception e) {
System.out.println("Exception in starting server: " + e.getMessage());
} finally {
out.close();
in.close();
echoSocket.close();
}
}
}
Here is my Client program:
public class Client {
public static String reply,temp;
public static boolean x=true;
public Client()
{
temp="lala";
}
public Client(String t)
{
temp=t;
}
public static void main(String[] args) throws IOException {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket("localhost", 77);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: localhost.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: localhost.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
temp="lala"; //this is the string to be sent
out.println(temp);
while (x) {
reply= in.readLine();
if(reply!=null)
{
x=false;
}
}
System.out.println("reply: "+reply);
out.close();
in.close();
stdIn.close();
echoSocket.close();
}
}
Can anyone help me find what the problem here is?
while (x) {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
reply = in.readLine();
if (reply != null) {
x = false;
}
}
Your server enters this loop the first time a client connects, and it sets the reply String to some input from the client. However, it never enters this loop again, as x's value never changes back to true.
When you accept a request, the x will be set false and never become true.
Please initial the x when you enter the loop.
What's more,if you use a socket between client and server, please move the
echoSocket = serverSocket.accept();
out of the first loop.And you can use echoSocket to communicate.Then you will
keep the long connection.