I have 2 important classes(client and server) and I will write something in my text area and by clicking on the send button I will call the active method of the client class and I will send that text to my client class,every thing is ok and that text also will be printed on the server console but I can not echo that text from server to client,please help me thanks.
client class:( a part of that)
os = new PrintWriter(c.getOutputStream(), true);
is = new BufferedReader(new InputStreamReader(c.getInputStream()));
public static void active() {
String teXt = MainClient.getText();
os.println(teXt);
String line = is.readLine();
System.out.println("Text received: " + line);
os.flush();
is.close();
is.close();
c.close();
server class:( a part of that)
BufferedReader streamIn = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter streamOut =new PrintWriter(client.getOutputStream());
boolean done = false;
String line =null;
while (!done ) {
line = streamIn.readLine();
if (line.equalsIgnoreCase("bye")) {
done = true;
} else {
System.out.println(line);
streamOut.println(line);
}
}
streamIn.close();
client.close();
server.close();
actually Nettogrof is going the correct way, but you must also flush the server side:
line = streamIn.readLine();
if (line.equalsIgnoreCase("bye")) {
done = true;
} else {
System.out.println(line);
streamOut.println(line);
streamOut.flush(); // or ...checkError();
}
or just create the PrintWriter with autoFlush set to true:
PrintWriter streamOut = new PrintWriter(client.getOutputStream(), true);
One note: you should also test if readLine() is returning null since the client will close the connection without sending a "bye".
A second note: instances of PrintWriter never throw IOExceptions, you should test for errors calling checkError(), which also flushes the stream.
You need to " os.flush(); " before reading the server answer.
Because according to your client code, you prepare the text to send with
String teXt = MainClient.getText();
os.println(teXt);
Then you wait for server answer by :
String line = is.readLine();
System.out.println("Text received: " + line);
Then you send your text to the server :
os.flush();
try :
String teXt = MainClient.getText();
os.println(teXt);
os.flush();
String line = is.readLine();
System.out.println("Text received: " + line);
Your server code implementation is wrong, streamIn,client and streamOut are never closed because of infinite loop.
Refer article mentioned by medopal for more help.
How frequently is the input stream being read? From the code, it looks like there is a single read, probably before anything has been sent from the server, and that's it. You'll probably have to do more consistent polling of the server if you're going to to use the approach you've taken.
Something like:
while (line = is.readLine() != null ) {
System.out.println("Text received: " + line);
}
Related
I'm implementing a client side software that lets user input commands, sends them to a server, the server interprets them and sends the result to the client. Here's where I'm stuck, I have a while loop that gets responses from server until the connection ends.
try(Socket socket = new Socket(hostname, port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))){
System.out.println("Connected to " + hostname + ":" + port + " !");
Scanner scanner = new Scanner(System.in);
String command = scanner.nextLine();
String fromServer = null;
int status;
HashMap<String, String> response;
long start = 0;
System.out.println("C:" + command);
if (command.toLowerCase().equals("exit")) return;
out.println(command);
if (command.toLowerCase().equals("shutdown")) return;
out.println();
while ((fromServer = in.readLine()) != null) {
// Here's my problem
response = parseResponse(fromServer);
if (response.containsKey("response")) response.put("response", response.get("response").replaceAll("\\\\n", "\n"));
try {
status = Integer.parseInt(response.get("status"));
} catch (NumberFormatException e){
status = Status.RESPONSE_CORRUPTED;
}
System.out.println("S:" + status + (response.get("response") != null ? "\n" + response.get("response") : ""));
command = scanner.nextLine();
System.out.println("C:" + command);
out.println(command);
}
} catch (IOException e){
System.out.println("Server isn't connected, try again later.");
}
The real problem is that I need to put
if (command.toLowerCase().equals("exit")) return;
out.println(command);
if (command.toLowerCase().equals("shutdown")) return;
out.println();
before the while, so there's three out.println() in the code while one would be more "logic" and I need to put
if (command.toLowerCase().startsWith("shutdown") && fromServer.equalsIgnoreCase("0") || status == Status.RESPONSE_CORRUPTED) break;
in that while so the client stops directly when the command shutdown is sent (to shutdown the server) to prevent the user from entering another command.
I'm searching for a more efficient way to manage commands and to add a ping command (but I need to add an if before the one to shutdown), maybe using more OOP but I don't see how to do it.
I think you should give a try to Spring Shell first before attempting to make your own from scratch. It is quite modular and you can create the backend handlers that send the commands to the remote server.
Use an infinite loop and break it based on the user input or on the server response
Here is an example which does not send the exit/shutdown commands to the server, but rather they only stop the client. If you need to send all the commands to the server and stop only based on the server response then just delete the if statement from the while loop
Scanner scanner = new Scanner(System.in);
String command = null;
while (true) {
command = scanner.nextLine();
if (command.toLowerCase().equals("exit") || command.toLowerCase().equals("shutdown")) {
break;
}
out.print(command);
out.flush();
String response = in.readLine();
// do something with the response (ex. stop the client by calling break or just print the response
}
I am currently learning Java, and I tried to make a simple chat program, which communicates between a server and a client. My problem is that the two programs connect properly to each other, but send messages do not get print out. I do not know whether it is the sending or receiving part. Do not judge my class naming, it is just temporarily.
The client-side part of receiving:
InputStream is = chatterSock.getInputStream();
OutputStream os = chatterSock.getOutputStream();
Thread readThread = new Thread(() -> {
while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
chatter.print("<p>" + out.toString() + "</p>");
} catch (IOException ex) {
chatter.printWarning("Connection lost");
}
}
The server-side part is pretty similar.
To send messages I just run
<Socket>.getOutputStream().write(<String>.getBytes());
I already tried some other posts from stackoverflow, but did not find a way that works. Thanks for your help!
Edit: here is the server side:
InputStream is = chatterSock.getInputStream();
OutputStream os = chatterSock.getOutputStream();
Thread readThread = new Thread(() -> {
while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
overlord.print("<p>" + out.toString() + "</p>");
} catch (IOException ex) {
overlord.chatterSockList.remove(overlord.chatterSockList.indexOf(chatterSock));
overlord.printWarning("Connection to " + chatterSock.getInetAddress() + " lost");
overlord.sendToAll(("User " + username + " disconnected."));
}
}
});
Edit: The message gets send here:
sendButton.addActionListener(e -> {
try {
chatterSock.getOutputStream().write((messageArea.getText()+"\n").getBytes());
messageArea.setText("");
} catch (IOException ex) {
System.err.println(ex);
printWarning("Connection lost"); //TODO heartbeat
}
});
As #Russell Uhl mentions in his comment, a read loop whose termination condition is reader.readLine()) != null is only going to terminate when the output stream is closed.
If the output stream is not closed, that call simply waits for new information, and shall continue to do so indefinitely.
It is also going to wait indefinitely if you don't send over a newline, which is why you were told to add it to your write command.
It would be best to process each line you read separately, rather than trying to append them to a buffer and output them all together. Do the processing inside the loop.
And probably it's also a good idea to add some button to your GUI to terminate the chat. It will disable the rest of the GUI and close the output stream, which in turn will cause the readLine() to return null, and the loop to terminate properly.
I send a message over sockets from an android app to a java program. This message is sent with a printwriter.
here is how I send my message from android to java program:
out.println("Hello there");
out.flush();
This is how I receive the message:
while(true){
String msg = in.readLine();
System.out.println("MSG: " + msg);
...some if-statements...
}
The output of the System.out.println is:
MSG: Hello there
*MSG: null*
How come I get null there? I'm only sending "hello there"..
Help would be appreciated, thanks!
EDIT: Actual code of the java program.
while (run) {
String msg = in.readLine();
String[] parts;
String username;
String password = null;
System.out.println("MSG: " + msg);
parts = msg.split("\\*");
username = parts[0];
password = parts[1];
boolean validUser = false;
validUser = db.authenticate(username, password);
if (validUser) {
db.updateIP(username, socket.getInetAddress().getHostAddress());
out.println("done");
out.flush();
} else {
out.println("loginfail");
out.flush();
closeSocketConnection();
}
}
}
private void closeSocketConnection() throws IOException {
in.close();
out.close();
socket.close();
run = false;
}
What is your exit condition for your while loop?
It looks to me like it is repeating and readLine will return null when the end of the stream has been reached causing MSG: null to be printed.
Updated given new information:
Assuming user*123 is a valid username/password combo then closeSocketConnection() is never called, the loop returns to the top, readLine returns null and you see your erroneous output. Followed by a NullPointerException on parts = msg.split("\\*");
Your loop should read:
while ((line = in.readLine()) != null)
{
// ...
}
At the moment you're processing the null that indicates end of stream inside the loop, hence you're printing it as a message when it isn't.
In the code below, what determines what will be sent back to the client (the PHP page). I am trying to alter this so that it sends a variable back to the PHP page with an error message that is defined based on actions made in my java code.
Edit: To answer some questions, what I am trying to do is this.
Send a string to the java script with a socket and convert it to a variable to be used in the java script. It will run through some if statements and I need to set the error statements to a variable lets say "reply". I need to send "reply" then back to the PHP file.
public class MyJavaServer {
public static void main(String[] args) {
int port = 20222;
ServerSocket listenSock = null; //the listening server socket
Socket sock = null; //the socket that will actually be used for communication
try {
listenSock = new ServerSocket(port);
while (true) { //we want the server to run till the end of times
sock = listenSock.accept(); //will block until connection recieved
BufferedReader br =
new BufferedReader(new InputStreamReader(sock.getInputStream()));
BufferedWriter bw =
new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
String line = "";
while ((line = br.readLine()) != null) {
bw.write("PHP said: " + line + "\n");
bw.flush();
}
//Closing streams and the current socket (not the listening socket!)
bw.close();
br.close();
sock.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
If I get your question right, the line where the answer gets sent to the peer is
bw.write("PHP said: " + line + "\n");
which writes the given string to bw.
I have a server which initially does this:-
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
for (;;) {
String cmdLine = br.readLine();
if (cmdLine == null || cmdLine.length() == 0)
break;
...
}
later it passes the socket to another class "foo"
This class wait for application specific messages.
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
appCmd=br.readLine();
My client sends this sequence:
"bar\n"
"how are u?\n"
"\n"
"passing it to foo\n"
"\n"
The problem is that sometimes "foo" does not get its response. It hangs in the readLine().
What is the chance that readLine() in the server is buffering up the data using the read ahead and "foo" class is getting starved?
If I add a sleep in the client side, it works. But what is the chance that it will always work?
"bar\n"
"how are u?\n"
"\n"
sleep(1000);
"passing it to foo\n"
"\n"
How to fix the problem? Appreciate any help on this regard.
eee's solution works perfectly. I was trying to read output from an SMTP conversation but it would block on:
while ((response = br.readLine()) != null) {
...Do Stuff
}
Changing to:
while (br.ready()) {
response = br.readLine();
...Do Stuff
}
I can read everything just fine. br is a BufferedReader object, BTW.
There is data already in the first BufferedReader (that has been read from the socket, and is no longer available from the socket), so pass the BufferedReader created in the first example to the class that reads the app specific messages, rather then creating a new BufferedReader from the socket.
I had the same problem and here is my solution:
try {
StringBuilder response = new StringBuilder();
response.append("SERVER -> CLIENT message:").append(CRLF);
//Infinite loop
while (true) {
//Checks wheather the stream is ready
if (in.ready()) {
//Actually read line
lastLineFromServer = in.readLine();
//If we have normal behavior at the end of stream
if (lastLineFromServer != null) {
response
.append(lastLineFromServer)
.append(CRLF);
} else {
return response.toString();
}
} else {//If stream is not ready
//If number of tries is not exceeded
if (numberOfTry < MAX_NUMBER_OF_TRIES) {
numberOfTry++;
//Wait for stream to become ready
Thread.sleep(MAX_DELAY_BEFORE_NEXT_TRY);
} else {//If number of tries is exeeded
//Adds warning that things go weired
response
.append("WARNING \r\n")
.append("Server sends responses not poroperly.\r\n")
.append("Response might be incomplete.")
.append(CRLF);
return response.toString();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
The answer might be late but this is the simplest and latest answer in 2020, just use the simple way to receive the data from the socket server or client using the input stream read() method.
EOFException will be thrown when the client is disconnected or the server closed the connection.
private String waitForData() throws IOException {
String data = "";
do {
int c = inputStream.read();
if (c > -1) data += (char) c;
else throw new EOFException();
} while (inputStream.available() > 0);
return data;
}