IOException: stream is closed, NullPointerException with HttpURLConnection disconnect - java

everyone. I'm coding a function that connects to a server by using Class HttpURLConnection. In the code, I establish a connection, call getOutputStream() and getInputStream() methods in order. Then I disconnect the connection. After this, I try to get data which has been obtained by getInputStream() method, but the compiler reminds NullPointerException.
Code in below:
DataOutputStream out = null;
InputStreamReader inStrReader = null;
BufferedReader reader = null;
HttpURLConnection connection = null;
try {
URL postUrl = new URL(null, url, new sun.net.www.protocol.https.Handler());
connection = (HttpURLConnection) postUrl.openConnection();
...//some setting methods
connection.connect();
out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(JSONObject.toJSONString(param));
out.flush();
out.close();
inStrReader = new InputStreamReader(connection.getInputStream(), "utf-8");
reader = new BufferedReader(inStrReader);
connection.disconnect(); //<--HERE, release the connection
StringBuilder stringBuilder = new StringBuilder();
for (String line = reader.readLine(); line != null; line = reader.readLine()) { //<--null pointer
stringBuilder.append(line);
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inStrReader != null) {
try {
inStrReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
After debug attempts, When I move the disconnection line to the last line in finally module, everything will be ok. But I'm confused, which happens when I already assgined the 'inputstream' value to 'reader'.
Thanks a lot.

Assigning isn't equal to reading, reader.readLine() start read from connection.
InputStreamReader is using the connection to read bytes, you disconnect before it read the bytes using the connection
An InputStreamReader is a bridge from byte streams to character
streams: It reads bytes and ...

Remember it is an "stream". You need to have an active connection to read from stream. Close the connection only after you have retrieved your data from stream.

You're doing everything in the wrong order. It doesn't make sense.
You're disconnecting and then expecting to be able to read from the connection. Total nonsense here. Normally you shouldn't disconnect at all, as you interfere with HTTP connection pooling. Just remove it, or, if you must have it, do it after all the closes.
You're closing in the wrong order, but you don't need to close inStrReader at all. Closing the BufferedReader does that. Just remove all the code for inStrReader.close().
You're closing out twice. Don't do that.
connect() happens implicitly. You don't need to call it yourself.
new URL(url) is sufficient. You haven't needed to provide the HTTPS Handler since about 2003.

Related

How to stop a BufferedReader after a certain amount of time in Android

I've got a thread that opens a socket that sends data to a server. The server may send data back depending if someone is at the work station. However I'm trying to put a timeout on the BufferedReader so that after 30 seconds it continues saying the response was null.
//Receive Response
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
response = new StringBuilder();
while ((line = bufferedReader.readLine()) != null ) {
response.append(line);
}
This is my BufferedReader, pretty standard, I've looked at a bunch of timers and other posts but haven't found a working solution.
You could call setSoTimeout() on your socket instance.
Itt will raise a SocketTimeoutException when the timeout is reached. Wrap your reading logic in a try-catch block, catch that exception and handle it as you wish.
Something like this:
try {
socket.setSoTimeout(30000);
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((line = bufferedReader.readLine()) != null ) {
response.append(line);
}
} catch (SocketTimeoutException ste) {
// timeout reached
} catch (Exception e) {
// something else happened
} finally {
// some general processing
}

Best way to handle (or) avoid too many "TCP_CLOSE_WAIT" state?

What is the reason for too many tcp close wait state in my server and how could i resolve this?
This is the sample snippet which my java client invokes to connect with server
HttpURLConnection urlConnection = (HttpURLConnection) (new URL(serverUrl).openConnection());
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(60000);
os = urlConnection.getOutputStream();
//Write to output stream
os.flush();
os.close();
urlConnection.connect();
is = urlConnection.getInputStream();
StringBuilder sb = new StringBuilder();
br = new BufferedReader(new InputStreamReader(is));
String eachLine = br.readLine();
while (eachLine != null && "".equals(eachLine) == false) {
sb.append(eachLine);
eachLine = br.readLine();
}
br.close();
is.close();
return sb.toString();
} catch (SocketTimeoutException se) {
System.out.println("Socket time out exception ");
} catch (Exception ioException) {
System.out.println("IO Exception ");
} finally {
try {
if (br != null) br.close();
} catch (IOException ioe) {
ioe.toString();
}
try {
if (is != null) is.close();
} catch (IOException ioe) {
ioe.toString();
}
try {
if (os != null) os.close();
} catch (IOException ioe) {
ioe.toString();
}
}
The following article suggests about keep-alive time and I could associate this with my client code which tries to connect it with the server.
The client can read error stream completely when exception occurred so that the underlying tcp connection could be reused.
When could I get too many tcp close_wait state and how can I avoid this?
What is the reason for too many tcp close wait state in my server and how could i resolve this?
Your server is leaking sockets. It is failing to detect client disconnects, or ignoring them, and not closing the socket.
The link you cite is irrelevant.
The cause is that your server code is not actively closing client connections by calling close(), leaving sockets in a state known as "half-closed".
To fix this issue, your server should detect when the connection was closed by the remote host and close the connection appropriately. If you fail to do this connections will stay in the CLOSE_WAIT state until the process itself is terminated and the OS closes all existing connections.
TCP connections actually consist of two half-connections which can be closed independently of each other. One end (like A in diagram below) can call close() on the socket, signaling that it will not send any more data, but the other end (like B in diagram below) may just ACK and continue sending data to A.
(A calls close())
A -----FIN-----> B
FIN_WAIT_1 CLOSE_WAIT
A <----ACK------ B
FIN_WAIT_2
(B can send more data here, this is half-close state)
(B calls close())
A <----FIN------ B
TIME_WAIT LAST_ACK
A -----ACK-----> B
| CLOSED
2MSL Timer
|
CLOSED

Send a string instead of byte through socket in Java

How can i send a strin using getOutputStream method. It can only send byte as they mentioned. So far I can send a byte. but not a string value.
public void sendToPort() throws IOException {
Socket socket = null;
try {
socket = new Socket("ip address", 4014);
socket.getOutputStream().write(2); // have to insert the string
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
socket.close();
}
}
Thanks in advance
How about using PrintWriter:
OutputStream outstream = socket .getOutputStream();
PrintWriter out = new PrintWriter(outstream);
String toSend = "String to send";
out.print(toSend );
EDIT: Found my own answer and saw an improvement was discussed but left out. Here is a better way to write strings using OutputStreamWriter:
// Use encoding of your choice
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(fileDir), "UTF8"));
// append and flush in logical chunks
out.append(toSend).append("\n");
out.append("appending more before flushing").append("\n");
out.flush();
Use OutputStreamWriter class to achieve what you want
public void sendToPort() throws IOException {
Socket socket = null;
OutputStreamWriter osw;
String str = "Hello World";
try {
socket = new Socket("ip address", 4014);
osw =new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
osw.write(str, 0, str.length());
} catch (IOException e) {
System.err.print(e);
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
socket.close();
}
}
Two options:
Wrap your OutputStream in an OutputStreamWriter, so you can then send the string
Convert a string to bytes using String.getBytes(encoding)
Note that in both cases you should specify the encoding explicitly, e.g. "UTF-8" - that avoids it just using the platform default encoding (which is almost always a bad idea).
This will just send the character data itself though - if you need to send several strings, and the other end needs to know where each one starts and ends, you'll need a more complicated protocol. If it's Java on both ends, you could use DataInputStream and DataOutputStream; otherwise you may want to come up with your own protocol (assuming it isn't fixed already).
if you have a simple string you can do
socket.getOutputStream().write("your string".getBytes("US-ASCII")); // or UTF-8 or any other applicable encoding...
You can use OutputStreamWriter like this:
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
out.write("SomeString", 0, "SomeString".length);
You may want to specify charset, such as "UTF-8" "UTF-16"......
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream(),
"UTF-8");
out.write("SomeString", 0, "SomeString".length);
Or PrintStream:
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("SomeString");
Or DataOutputStream:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes("SomeString");
out.writeChars("SomeString");
out.writeUTF("SomeString");
Or you can find more Writers and OutputStreams in
The java.io package
public void sendToPort() throws IOException {
DataOutputStream dataOutputStream = null;
Socket socket = null;
try {
socket = new Socket("ip address", 4014);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF("2"); // have to insert the string
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
if(socket != null) {
socket.close();
}
if(dataOutputStream != null) {
dataOutputStream.close();
}
}
}
NOTE: You will need to use DataInputStream readUTF() method from the receiving side.
NOTE: you have to check for null in the "finally" caluse; otherwise you will run into NullPointerException later on.
I see a bunch of very valid solutions in this post. My favorite is using Apache Commons to do the write operation:
IOUtils.write(CharSequence, OutputStream, Charset)
basically doing for instance:
IOUtils.write("Your String", socket.getOutputStream(), "UTF-8")
and catching the appropriate exceptions. If you're trying to build some sort of protocol you can look into the Apache commons-net library for some hints.
You can never go wrong with that. And there are many other useful methods and classes in Apache commons-io that will save you time.
Old posts, but I can see same defect in most of the posts. Before closing the socket, flush the stream. Like in #Josnidhin's answer:
public void sendToPort() throws IOException {
Socket socket = null;
OutputStreamWriter osw;
String str = "Hello World";
try {
socket = new Socket("ip address", 4014);
osw =new OutputStreamWriter(socket.getOutputStream(), 'UTF-8');
osw.write(str, 0, str.length());
osw.flush();
} catch (IOException e) {
System.err.print(e);
} finally {
socket.close();
}
}

Java client socket using writeBytes

I'm reading a string from a buffer and writing it to a server. The problem I'm having is that the string never gets received by the server when I leave the socket open and write in a loop.
When I use this:
try {
Socket send = new Socket("localhost", 1490);
DataOutputStream out = new DataOutputStream(send.getOutputStream());
String message = null;
while ((message = buffer.get()) != null){
out.writeBytes(message);
}
out.close();
send.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
the server doesn't receive the string, but when I do this it works properly:
try {
String message = null;
while ((message = buffer.get()) != null){
Socket send = new Socket("localhost", 1490);
DataOutputStream out = new DataOutputStream(send.getOutputStream());
out.writeBytes(message);
out.close();
send.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
Obviously I don't want to keep opening and closing the socket, though. What is the problem?
You need to flush your socket every time you want to send a data packet.
Closing a socket forces an automatic flush and that explains why your data is getting sent on socket close.
The data is not being written to the socket even when you close it? (in your first snippet that is)
Also, have you tried to use the flush method? You can read about it here: http://docs.oracle.com/javase/1.4.2/docs/api/java/io/DataOutputStream.html#flush() and your code will look like:
try {
Socket send = new Socket("localhost", 1490);
DataOutputStream out = new DataOutputStream(send.getOutputStream());
String message = null;
while ((message = buffer.get()) != null){
out.writeBytes(message);
out.flush();
}
out.close();
send.close();
} catch (IOException ex) {
ex.printStackTrace();
}
Let me make a guess.
Does the buffer.get() method block? If so, then the problem is that out.writeBytes(message) does not guarantee that the entire byte representation to be pushed to the server. Instead. there is a good chance that your client has buffered bytes waiting to be flushed through to the server.
If this is what is going on, then calling flush after each call to writeBytes will fix the problem.
But if the buffer.get() method doesn't block, then calling flush won't make any difference. In fact, it will just increase the network traffic. So adding the flush "just in case" is a bad idea.
Another possibility is that there is something wrong with the server-side code.

Will setting a timeout on a socket work if you are reading a full line using a buffered reader?

I'm writing a socket client that sends a line down a socket connection and then waits for up to 45 seconds for a line back from the server.
I'm using a buffered reader like so:
Socket socket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
socket = new Socket(host, 800);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
} catch (UnknownHostException e) {
listener.failedToConnectToHost(e);
return;
} catch (IOException e) {
listener.failedToConnectToHost(e);
return;
}
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
out.println("message");
try {
String response = in.readLine();
listener.responseRecived(response);
return;
} catch (IOException e) {
listener.errorReadingResponse(e);
return;
}
If I add the following line (Or something like it)
socket.setSoTimeout(45000);
What will happen after 45 seconds assuming that nothing has come through from the other end?
I assume I'll be catching an interrupted exception but I'm sure?
Will this even work? The docs for setSOTImeOut() imply that it's socket.read() that will timeout, I assume that the buffered reader is calling this somewhere down the stack, but assumption is the mother of all screw ups, so I just wanted to check.
The BufferedReader.readLine() method will throw a SocketTimeoutException after 45 seconds.
Apparently it does work and you get a SocketTimeoutException.

Categories