BufferedReader reads line only after closing the connection, not after flush() - java

I've the following Server.java:
public class Main {
public static void main(String args[]) throws Exception{
ServerSocket server = new ServerSocket(12345);
Socket client = server.accept();
OutputStream out = client.getOutputStream();
BufferedWriter writer = new BufferedWriter(new PrintWriter(out));
writer.write("Hello client");
writer.flush(); //After executing of that instruction there is no any output on the client
client.close(); //The client prints "Hello client"
}
}
and the Client.java:
public class Main {
#SuppressWarnings("resource")
public static void main(String args[]) throws Exception{
Socket s = new Socket("localhost", 12345);
BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(r.readLine());
s.close();
}
}
The issue is I can't get the reason why the client prints the string only after the connection was closed, but not after the stream was flushed. I thought flush() send a signal to the client that data-transfering process is over. Since, the client have to read all the data that was being send to it before calling flush(). What's wrong?

readLine() reads a complete line. To know that the line is complete, the reader needs to either find a newline character sequence, or the end of the stream. So it blocks until it sees one of those.
Realize that your client might very well do the following:
out.write("Hello ");
out.flush();
out.write("world!\n");
out.flush();
This sends a single line: "Hello world". And readLine() as its name indicates, is supposed to return that, not 2 lines "Hello " and "World".
So, if you want to send a line, you need to end its line terminator. Otherwise you're not sending a line, but only some characters.
Note that it would be easier if you used a PrintWriter correctly:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));
out.println("Hello client");

Related

Print Writer write() and println()

I am currently learning Java Network programming. In one of my Programs I just have an EchoServer which sends the message of the client. But I recognized in the client that the Printwriter.write() method just sends when I close the writer while the .println() method works fine. I also tried it with and without auto-flush.
Works:
public static void main(String[] args) {
System.out.println("Simple Echo Client");
try{
System.out.println("Waiting for Connection ...");
InetAddress localAdress = InetAddress.getLocalHost();
try(Socket clientSocket = new Socket(localAdress,6000);
PrintWriter out =new PrintWriter(clientSocket.getOutputStream(),true);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))){
System.out.println("Connected to Server");
Scanner scanner = new Scanner(System.in);
while(true){
System.out.print("Enter text: ");
String inputLine = scanner.nextLine();
if("quit".equals(inputLine)){
break;
}
out.println(inputLine);
String response = br.readLine();
System.out.println("Server response" + response);
}
}
}catch(IOException ex){
ex.printStackTrace();
}
}
Doesn't work:
public static void main(String[] args) {
System.out.println("Simple Echo Client");
try{
System.out.println("Waiting for Connection ...");
InetAddress localAdress = InetAddress.getLocalHost();
try(Socket clientSocket = new Socket(localAdress,6000);
PrintWriter out =new PrintWriter(clientSocket.getOutputStream(),true);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))){
System.out.println("Connected to Server");
Scanner scanner = new Scanner(System.in);
while(true){
System.out.print("Enter text: ");
String inputLine = scanner.nextLine();
if("quit".equals(inputLine)){
break;
}
out.write(inputLine);
String response = br.readLine();
System.out.println("Server response" + response);
}
}
}catch(IOException ex){
ex.printStackTrace();
}
}
Could somebody explain to me why this is the case?
the Printwriter.write() method just sends when I close the writer while the .println() method works fine
There seems there may be two problems here, the first having to do with writing and the second with reading:
The code creates a PrintWriter with automatic line flushing. When you use println, the new line results in the writer flushing. When using write without a new line, the PrintWriter does not flush (you can call out.flush after out.write to force a flush of the Writer).
Presuming the receiving end is using Scanner.readLine(), it expects a new line or will wait until it receives one. println automatically appends the new line to the end of the String, with write you must explicitly send the new line out.write(line + "\n");
Yes I've absolutely seen this before. If you are using a PrintWriter or another Writer that has autoflush, you do not need to call flush(). But otherwise, to get the message to send, you've got to call flush() to get the content in the Writer / OutputStream to send.

Client/Server Program in Java - Streams

I have a problem getting the output that i want from the code that i have implemented in order to create the server/client program...it's just a really simple one, and i don't know why i don't get what i want.
Here is the code of the server:
ServerSocket serverSocket = new ServerSocket(1025);
System.out.println("Porting...");
Socket socket = serverSocket.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = in.readLine();
System.out.println("Server read: " + s);
out.write("Got it");
socket.close();
System.out.println("Server Exit");
The client:
System.out.print("Connecting...");
Socket socket = new Socket("localhost",1025);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.write("Hello, Server");
String s = in.readLine();
System.out.println("Client Recieved: " + s);
socket.close();
System.out.println("Client Exit");
I try to get the Hello, Server output, instead i just get the "connecting" syso from the client (which i just did to see if it works)
Once you wrote on the stream you have to flush the stream by calling flush() method on the outputstream. Else the stream will be flushed once the stream buffer is full.
out.flush();
Also you have to make sure that enter the new line character to mention the end of line. Because readLine() waits for string with newline().
A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r')
out.write("Hello, Server\n");
out.flush();

Sends files from client to server

In the below codes,I am trying to let the server-side to select the file from the client and sends it, so basically all the work is done on the server side. the program works by running the server first wait for client to run, make a connection, then the server sends the place of the file to the client-side outReader.write("B://ghassar/ghassar.txt"); the client reads the location and sends the file. I have run the debug and once the server reads this code String filename = inReader.readLine(); it stops and it gets in like a loop, can anyone help me to solve the problem
/ Server.java
/*
* Server waits for a connection to be established by client
*
*/
import java.io.*;
import java.net.*;
class Server
{
public static void main(String args[])throws Exception
{
System.out.println("Server running...");
/* Listen on port 5555 */
ServerSocket server = new ServerSocket(222);
/* Accept the sk */
Socket sk = server.accept();
System.out.println("Server accepted client");
// to recive from client
InputStream input = sk.getInputStream();
//read what is coming
BufferedReader inReader = new BufferedReader(new InputStreamReader(sk.getInputStream()));
//write to client
BufferedWriter outReader = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
outReader.write("B://ghassar/ghassar.txt");
outReader.flush();
/* Read the filename */
String filename = inReader.readLine();
if (filename.equals("ghassar.txt") ){
/* Reply back to client with READY status */
outReader.write("READY\n");
outReader.flush();
}
/* Create a new file in the libya directory using the filename */
FileOutputStream wr = new FileOutputStream(new File("B://libya/ "+ filename));
byte[] buffer = new byte[sk.getReceiveBufferSize()];
int bytesReceived = 0;
while((bytesReceived = input.read(buffer))>0)
{
/* Write to the file */
wr.write(buffer,0,bytesReceived);
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
public class Client {
public static void main(String args[]){
Client clientForm = new Client();
clientForm.action();
}
public void action() {
try{
/* Try to connect to the server on localhost, port 5555 */
Socket sk = new Socket("localhost", 222);
OutputStream output = sk.getOutputStream();
/* the steam to send the staff*/
OutputStreamWriter outputStream = new OutputStreamWriter(sk.getOutputStream());
/* steam to recive staff */
BufferedReader inReader = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String serverStatus = inReader.readLine(); // Read the first line
String filename = serverStatus;//fileDlg.getSelectedFile().getAbsolutePath();
outputStream.write("ghassar.txt");
outputStream.flush();
/* If server is ready, send the file */
if ( serverStatus.equals("READY") ){
FileInputStream file = new FileInputStream(filename);
byte[] buffer = new byte[sk.getSendBufferSize()];
int bytesRead = 0;
while((bytesRead = file.read(buffer))>0)
{
output.write(buffer,0,bytesRead);
}
output.close();
file.close();
sk.close();
System.out.println("File sent");
}
}
catch (Exception ex){
/* Catch any errors */
System.out.println("not File sent");
}
}
}
I suggest you to use PrintWriter instead of BufferedWriter. There is no need to call flush after each line and simply use println() method along with auto-flush feature to add a new line as well.
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output.
These methods use the platform's own notion of line separator rather than the newline character.
There is no need to append \n in the message itself.
Sample code:
// here true means auto flush when `println()` method is called
PrintWriter w=new PrintWriter(new OutputStreamWriter(sk.getOutputStream()),true);
w.println(message);
Possible cause in the code:
The problem may be at below lines where \n is not added in the end of the string in write() method before flushing and at client side the method readLine() is used to read it.
BufferedWriter outReader = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
outReader.write("B://ghassar/ghassar.txt");
outReader.flush();
Note: you can use BufferedWriter#newLine() instead of \n that writes a line separator. The line separator string is defined by the system property line.separator, and is not necessarily a single newline ('\n') character.

Java Socket server side cannot read incoming line of text in play framework application

So I'm having some serious problems with Java's server side socket, which accepts connection, but it can't read anything from BufferedReader, which I have put to read the text stream from socket connection. Code for my threads run(), which I'm creating and running at the first time when any page is loaded.
public void run() {
try{
ServerSocket s = new ServerSocket(4100);
System.out.println("New tcp socket created");
Socket socket = s.accept();
System.out.println("New tcp update connection established.");
InputStream din = socket.getInputStream();
PrintWriter outp = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(din));
System.out.println("Streams created");
String inputline = "nothing yet...";
outp.println("hello from server");
while(true){
System.out.println("Got input from client:" + inputline);
inputline = in.readLine();
if(inputline == null || inputline.equals("exit")){
break;
}
}
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("Updater thread exits.");
}
This prints out everything properly, except for Got input from client: + what ever my client sends with PrintWriter which outputs to a socket.
Client side example:
Socket s = new Socket(serverip, serverDownloadsUpdatePort);
OutputStream dout = s.getOutputStream();
PrintWriter outp = new PrintWriter(dout);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(in.readLine());//This prints out properly, what server sends to client
outp.println("test connection");
outp.println("Can you hear me?");
outp.println("exit");
s.close();
Your client may not be sending end-of-line characters along with its input, causing your server to wait indefinitely at "in.readLine()".
The Javadoc for BufferedReader's readLine method (http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine()) says: "Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed." Make sure that your client is sending input that conforms to this rule.
I was able to see client input using your server with the following client Runnable (but only if I include the "\n"):
public void run() {
try{
Socket writeSocket = new Socket("localhost", 4100);
PrintWriter out =
new PrintWriter(writeSocket.getOutputStream(), true);
out.write("Hello there!\n");
out.flush();
}
catch(Exception e){
e.printStackTrace();
}
}
EDIT: When using println as in the submitter's client example, you don't need to worry about adding "\n", but you do need to flush the socket. One way to make sure this happens is by setting autoFlush=true in the PrintWriter constructor.
I found out that I forgot to set PrintWriter as auto flushable at client side and thats why it didn't work becouse stream didn't got flushed at any time.

TCP Client/Server

I have this code and for some reason it stucks at readline() line at servers end always waiting from client but client on the other end sends the data.
Both the server and client's code is available below.
Server Code
import java.io.*;
import java.net.*;
public class TCPServer {
public static final int SERVER_PORT = 6789;
public static void main(String argv[]) throws Exception {
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(SERVER_PORT);
while (true) {
Socket connectSocket = welcomeSocket.accept();
InputStream sin = connectSocket.getInputStream();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(sin));
PrintWriter outToClient = new PrintWriter(connectSocket.getOutputStream(), true);
clientSentence = inFromClient.readLine();
capitalizedSentence = clientSentence.toUpperCase() + "\r\n";
outToClient.print(capitalizedSentence);
}
}
}
Client Code
import java.io.*;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws Exception {
String hostName = "localhost";
int port = 6789;
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket(hostName, port);
PrintWriter outToServer = null;
clientSocket.getOutputStream();
BufferedReader inFromServer = null;
inFromServer=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.print(sentence + "\r\n");
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " +modifiedSentence);
clientSocket.close();
}
}
After fixing your syntax errors around outToServer, I think the problem lies in the way you're using PrintWriter around the output stream on the client's side. From the documentation:
Unlike the PrintStream class, if automatic flushing is enabled it will
be done only when one of the println, printf, or format methods is
invoked, rather than whenever a newline character happens to be
output. These methods use the platform's own notion of line separator
rather than the newline character.
Since you're using print with a manually appended new line, the message is never flushed to the socket's output stream. I believe you can fix this by using println instead:
outToServer.println(sentence);
Even better would be to use DataInputStream and DataOutputStream instead of BufferedReader and PrintWriter, as those are better suited for sending and receiving arbitrary data over a socket stream.

Categories