Class c extends thread
static Queue<Socket> socketQueue
Make connection to another server or client
And then add socket to socketqueue
Class a extends thread
method a
bufferedinputstream bis = socketQueue.poll
Do work
Make bis null without closing it<br>
Class b extends thread
Method b
Bufferedinputstream bis = socketqueue.poll
Do work
Make bis null without closing it
I did make bufferedinput stream null since i do not want to close the connected socket. Several posts were telling me that closing input/output stream would close the socket as well.
Whenever I use input/output stream with socket, I usually close stream and socket if its not null.
What I am trying to do here is to make the socket alive and reuse when input or output stream is needed without connecting again.
I tried socket.shutdowninput and output, however, this throws an exception when i make another input/output stream with the socket.
Is there anything I have misunderstood or am missing at this point?
A connection over a socket only ever has one InputStream and one OutputStream. As soon as you close any of those (or the Socket itself) the connection is automatically closed. You need to store the streams you need somewhere and use those, you can not get them from the same Socket each time you need them.
Related
If I create a Channel from an InputStream, and then close the InputStream, will it close the associated Channel? Do I need to close the associated Channel explicitly? I know closing Channel will close Stream, but what about the reverse?
try (InputStream ioStream = getInputStream()) {
ReadableByteChannel inputChannel = Channels.newChannel(ioStream);
//do something
}
In the general case, the InputStream knows nothing about the Channel, so closing the InputStream cannot automatically close the Channel.
However, trying to read from the Channel after the InputStream has been closed will throw an IOException:
the channel has to fetch data from the inputstream through InputStream.getBytes()
InputStream.getBytes() will throw an IOException if the inputstream has been closed.
For the special case of a FileInputStream the Channels.newChannel(ioStream) call will return FileInputStream.getChannel(), so in this special case closing the inputstream will also close the channel.
Looking at the implementation of Channels.newChannel:
public static ReadableByteChannel newChannel(InputStream in) {
Objects.requireNonNull(in, "in");
if (in.getClass() == FileInputStream.class) {
return ((FileInputStream) in).getChannel();
}
return new ReadableByteChannelImpl(in);
}
As you can see, if the input stream is a file stream we have a special case. In this special case the close() method of the resulting channel will just return ! checked, where checked is a private boolean field of the corresponding file input stream. When you close the file input stream it sets the closed to true and then the channel will also think that it's closed:
InputStream is = new FileInputStream(new File("test.file"));
ReadableByteChannel channel = Channels.newChannel(is);
System.out.println(channel.isOpen()); // True
is.close();
System.out.println(channel.isOpen()); // False
However, this is an implementation detail, so you can't rely on it. Also, if the input stream is not a file input stream, then the above will not work at all.
I assume the core of your concern is that you don't have a "leak" by leaving resources open.
As far as I'm aware, so long as the underlying resource gets closed you won't have a leak since that underlying object (with native methods) is what's talking to the OS and keeping the resource open.
Since the documentation says that it simply redirects to the stream (emphasized in bold by me) then closing the InputStream itself will close the only actual resource as Channel.newChannel(InputStream) is not creating a new resource.
I would, however, rather open your Channel in a try-with-resources and let it be closed automatically, which will cascade to the underlying resource.
User Slaw has the correct idea that the InputStream has no knowledge of the Channel (except in the special case of a FileInputStream as shown by Alex). This is one of the reasons you should close your wrapper resources rather than just the underlying resources, so that your wrappers have consistent knowledge of the actual resource.
java.nio.channels.Channels.newChannel(InputStream) - Java 1.8 API
Constructs a channel that reads bytes from the given stream.
The resulting channel will not be buffered; it will simply redirect its I/O operations to the given stream. Closing the channel will in turn cause the stream to be closed.
Parameters:
in - The stream from which bytes are to be read
Returns:
A new readable byte channel
From Java API 7:
The resulting channel will not be buffered; it will simply redirect its I/O operations to the given stream. Closing the channel will in turn cause the stream to be closed.
Hope it helps!
How to close java client socket correctly?
is it necessary to close the socket.getOutputStream?
is it necessary to close the socket.getInputStream?
is it necessary to call socket.shutdownInput () ?
is it necessary to call socket.shutdownOutput () ?
What should be the sequence of calls (before|after) socket.close()?
The Socket documentation states:
Closing this socket will also close the socket's InputStream and OutputStream.
You don't have to shutdown the input/output. However that does allow you to "half" close the socket. Say if you wanted to continue to send data, but want to indicate you will no longer receive it.
So in short; It's completely fine to do the following:
...
finally {
if (socket != null)
socket.close();
}
I have a program like that,
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
...some read and write here...
socket.close;
The code works fine. But I am not sure whether the in/out was close if I close the socket or not. Also I didn't call out.flush(), how the data going to be sent out?
Closing the socket doesn't flush the output stream but closes both streams and the socket.
Closing the input stream doesn't flush the output stream but closes both streams and the socket.
Closing the output stream flushes it and closes both streams and the socket.
You should close the outermost OutputStream you have wrapped around the one you got from the socket. For example:
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
Close 'dos'. That flushes it, flushes 'bos', and closes everything.
Flush on close is documented in the Javadoc for FilterOutputStream.
Another answer: In Java, when I call OutputStream.close() do I always need to call OutputStream.flush() before?
says that yes! It will be flushed if you close it manually
I have a problem with a BufferedOutputStream. I want to send a kml file from an Android device to a java server through a socket connection.
(The connection is ok, i am already able to exchange data with a PrintWriter in an other part of my program)
To send my kml file, I fill the buffer. But when i flush() it, nothing happen.
int lu = inFile.read();
while(lu != -1){
out.write(lu);
lu = inFile.read();
}
out.flush();
inFile.close();
inFile is my stream used to read the kml file
out is my BufferedOutputStream using the OutputStream of my socket
I don't close my out object but i don't want to, i don't use it just once. And this is the problem...
The close() method send the buffer's data but close the socket too.
The flush() method does not send the buffer's data.
I want to flush the buffer without closing my socket.
I also tried to use mySocket.shutdownOutput();
int lu = inFile.read();
while(lu != -1){
out.write(lu);
lu = inFile.read();
}
out.flush();
mySocket.shutdownOutput();
inFile.close();
This method close my stream and keep my socket open, that's what i want.
But when i try to open a new output stream, the Exception java.net.SocketException: Socket output is shutdown
So, how to flush my buffer without closing my sokcet are being unable to open a new output stream ?
Socket.close() and Socket.shutdownOutput() both send an EOS to the peer, on which he should close the socket, and after which you can no longer write to the socket, because you've closed it in that direction.
So if you need to continue writing to the socket you cannot use either of these methods.
Probably what you are searching for is a way to delimit application protocol messages. There are at least three techniques:
Send a length word prior to each message.
Send an out-of-band delimiter after each message, i.e. a byte or byte sequence that cannot occur in a message. The STX/ETX protocol, with escapes, is an example of this.
Use a self-describing message format such as Object Serialization or XML. STX/ETX is also an example of this.
I have two 'Client's, one 'Server' and potentially a 'ThreadManager' that implements runnable.
The two Clients connect with Server via TCP and partake in a protocol handshake/ authentication thing (successful), then I attempted to pass the existing BufferedReaders, DataOutputStreams and Sockets to 'ThreadManager' to manage threading messages between Client1 and Client2:
SERVER:
ThreadManager tManager = new ThreadManager(serviceToClient1, inputStream, outputStream, serviceToClient2, inputStream2, outputStream2);
new Thread(tManager).start();
serviceToClient1.close();
serviceToClient2.close();
THREADMANAGER:
public ThreadManager(Socket cli1, BufferedReader inputStream, DataOutputStream outputStream, Socket cli2, BufferedReader inputStream2, DataOutputStream outputStream2)
{
this.cli1 = cli1;
this.inputStream = inputStream;
this.outputStream = outputStream;
this.cli2 = cli2;
this.inputStream2 = inputStream2;
this.outputStream2 = outputStream2;
}
this constructs successfully, however on .start() called from Server, debugging shows a "Socket Exception: Socket Closed" error as soon the following is called from within ThreadManager:
outputStream.writeBytes("NUMBER: " + i + "\n");
I'm not sure where the problem is created, would I need to close connections and recreate Sockets and streamreaders/writers from within ThreadManager? I tried only passing the Sockets in the ThreadManager constructor and then creating new BufferedReader... etc. but this seems to be just as bad. Could anyone suggest either the solution, or where the problem lies (or both!) :) thanks.
You close your Socket before you try to read from it on your Thread, so you get an exception.