Socket's PrintWriter doesn't send until closed - java

I have client code that looks like:
Socket s = new Socket(server.getHostName(), server.getPort());
PrintWriter p = new PrintWriter(s.getOutputStream());
p.println(message);
p.flush();
s.shutdownOutput();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String newLine;
StringBuffer response = new StringBuffer();
while((newLine = br.readLine()) != null)
response.append(newLine);
System.out.println(response.toString());
p.close();
br.close();
and server code that looks like:
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String nextLine;
StringBuffer request = new StringBuffer();
System.out.println("Starting read....");
String nextline;
while((nextline = br.readLine()) != null){
System.out.println(nextline);
request.append(nextline);
}
System.out.println("Message recived!!");
System.out.println("Request: " + request);
PrintWriter p = new PrintWriter(s.getOutputStream());
p.println("Hello, fileclient!");
System.out.println("Message sent!!");
p.close();
br.close();
Before I put the line s.shutDownInput() the server code would hang at br.readLine(). The way I managed to fix that is to close the PrintWriter some how, either through p.close() or through the current way which doesn't
shutdown the socket like closing the PrintWriter through p.close() does. After that, the interaction between client and server is perfect.
Why does the PrintWriter or the BufferedReader not send/receive until the PrintWriter is closed somehow?

It doesn't have anything to do with PrintWriter. It is an application protocol error on your part.
The server is looping reading lines until end of stream.
The client is sending one line and then not closing the socket, so no end-of-stream got sent (until you added the shutdown).
The server is then responding.
The client is then reading.
So the client doesn't read anything until the server gets out of the loop, and the server doesn't get out of its loop because the client is reading not closing.
So make up your mind. Probably the server should only read one line.

Both sides are behaving exactly as you told them to do. In particular, you instruct the server specifically to read everything the client sends before dispatching any response:
String nextline;
while((nextline = br.readLine()) != null){
System.out.println(nextline);
request.append(nextline);
}
It is important to understand that that will not stop reading until an error or end of stream, where end of stream on a socket corresponds to the other end having been closed and all data having been read. In other words, your server waits for the end of the whole conversation, not the end of a single message, before dispatching a response.
Since that's apparently not what you want, you need to implement a different strategy at the server for determining when to process the data received so far and send a response. If you can be confident that your messages will not contain internal newlines, then that might be as simple as the server performing only one br.readLine() before sending each response.

Related

PrintWriter print vs println

I got a server waiting for messages and a client sending him messages, when using
PrintWriter out = new PrintWriter(lpSocket.getOutputStream(), true);
String msg;
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
while ((msg = userIn.readLine()) != null)
out.print(msg + (char) 10);
nothing happens, meaning the server just keep waiting for a message that never arrive. When I change the out.print to out.println it works.
I would like to know why
By default, PrintWriter calls flush in println, whereas it doesn't do this in print. You can fix this by adding out.flush() after your out.print call

Java socket client: waiting for the response patiently

I have created a server via sockets with the help of quickserver.org. The server runs solidly.
Now I had to write the client that sends a request (just a string value) to the server for an instruction and waits for its response (xml as string). This works fine when the triggered process by the request on server is not very time consuming. Unfortunately the client connection breaks as far as the server needs a long time for the process and that leads for a connection break and the client doesn't get anything back.
Here is the client code:
public String sendAndReceive(String message) throws IOException {
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(this.socket.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
printWriter.print(message);
printWriter.flush();
this.socket.shutdownOutput();
String line = null;
StringBuilder xmlResponse = new StringBuilder();
while ((line = reader.readLine()) != null)
{
xmlResponse.append(line);
}
printWriter.close();
reader.close();
this.socket.close();
return xmlResponse.toString();
}
This method sends the request and waits for the response afterwards. I am not sure about the while loop but all examples I have found on web are praising this construction. On my point of view reader.readline() can be null because the server needs more time for the response and therefore the method ends without getting the response.
How is the best practice for socket clients waiting for the response patiently? What I am doing wrong?
Kind regards,
Hilderich
You are probably getting timeout.
You can use Socket.setSoTimeout(int timeout) to change timeout (in milliseconds).

Sending a JSON object over TCP with Java

I'm trying to replace a Netcat command that I'm running in my terminal that will reset some data on a server. The netcat command looks like this:
echo '{"id":1, "method":"object.deleteAll", "params":["subscriber"]} ' | nc x.x.x.x 3994
I've been trying to implement it in Java since I would like to be able to call this command from an application I'm developing. I'm having issues with it though, the command is never executed on the server.
This is my java code:
try {
Socket socket = new Socket("x.x.x.x", 3994);
String string = "{\"id\":1,\"method\":\"object.deleteAll\",\"params\":[\"subscriber\"]}";
DataInputStream is = new DataInputStream(socket.getInputStream());
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.write(string.getBytes());
os.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
The code also hangs on the while loop that should read the InputStream, I have no idea why. I've been using Wireshark to capture the packets and the data that is going out looks the same:
{"id":1,"method":"object.deleteAll","params":["subscriber"]}
Perhaps the rest of the packets are not shaped in the same way but I really can't understand why that would be. Perhaps I am writing the string in a faulty way to the OutputStream? I have no idea :(
Note that I posted a question similar to this yesterday when I didn't properly understand the problem:
Can't post JSON to server with HTTP Client in Java
EDIT:
These are the possible results I get from running the nc command, I would expect to get the same messages to the InputStream if the OutputStream sends correct data in a correct way:
Wrong arguments:
{"id":1,"error":{"code":-32602,"message":"Invalid entity type: subscribe"}}
Ok, successful:
{"id":1,"result":100}
Nothing to delete:
{"id":1,"result":0}
Wow, I really had no idea. I experimented with some different Writers like "buffered writer" and "print writer" and it seems the PrintWriter was the solution. Although I couldn't use the PrintWriter.write() nor the PrintWriter.print() methods. I had to use PrintWriter.println().
If someone has the answer to why other writers wouldn't work and explain how they would impact the data sent to the server I will gladly accept that as the solution.
try {
Socket socket = new Socket(InetAddress.getByName("x.x.x.x"), 3994);
String string = "{\"id\":1,\"method\":\"object.deleteAll\",\"params\":[\"subscriber\"]}";
DataInputStream is = new DataInputStream(socket.getInputStream());
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
PrintWriter pw = new PrintWriter(os);
pw.println(string);
pw.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
I think the server is expecting newline at the end of the message. Try to use your original code with write() and add \n at the end to confirm this.

Java: BufferedReader and OutputStream

I've got the following code, I'm trying to send data text by sockets. But when I try to send via PrintWriter, my client does nothing and it stops at in.readLine(). However when I use simply OutputStream and send it as bytes, my client doesn't have any problem with reading. Is it possible to as I want ?
out = new PrintWriter(sock.getOutputStream());
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
while (true) {
System.out.println("SERVER-THREAD: IP "
+ sock.getInetAddress().getHostAddress());
out.write(marshall() + "\n");
Thread.sleep(1000);
}
//Client
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream());
while (updateList) {
System.out.println("Before");
String inputip = in.readLine();
System.out.println("CLIENT: " + inputip);
//unmarshall(in);
System.out.println("After");
Thread.sleep(1000);
}
PrintWriter buffers the data to be written so it will not do so until the buffer is full. You need to call flush here
out.flush();
When you perform a readLine() it waits until it has a read a whole line. i.e. a new line.
Your send is sending text without a newline so the receive waits for something which will not happen.
A more basic problem is that you are mixing text and binary which is more likely to confuse than be useful.
I suggest you write text with PrintWriter.println() which you can read with BufferedReader.readLine().

Java socket, set connect timeout and so timeout, but still stuck when getting inputStream

Here's my code
Socket s = new Socket();
s.setSoTimeout(5000);
s.connect(url, 5000);
InputStreamReader inputStreamReader = new InputStreamReader(s.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
So connect timeout and read timeout are set
but i met a link :
http://scfire-mtc-aa01.stream.aol.com:80/stream/1023
My code stucked at this line :
bufferedReader.readLine();
now I check content-type of input stream before calling
bufferedReader.readLine();
to avoid this problem,
but I am still wondering why
bufferedReader.readLine();
stuck?
thanks for any help
You're talking to HTTP sites but you aren't sending any HTTP requests. So you don't get any HTTP responses. You are waiting for the response but the server is still waiting for the request.
Don't use Sockets for this, use URLs and URLConnections.

Categories

Resources