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();
}
Related
I have implemented a socket with a server and single client. The way it's structured currently, the server closes whenever the client closes. My intent is have the server run until manual shutdown instead.
Here's the server:
public static void main(String args[])
{
;
try
{
ServerSocket socket= new ServerSocket(17);
System.out.println("connect...");
Socket s = socket.accept();
System.out.println("Client Connected.");
while (true)
{
work with server
}
}
catch (IOException e)
{
e.getStackTrace();
}
}
I've tried surrounding the entire try/catch loop with another while(true) loop, but it does nothing, the same issue persists. Any ideas on how to keep the server running?
It looks like what's going to happen in your code there is that you connect to a client, infinitely loop over interactions with the client, then when someone disrupts the connections (closes clearning, or interrupts it rudly - e.g., unplug the network cable) you're going to get an IOException, sending you down to the catch clause which runs and then continues after that (and I'm guessing "after that" is the end of your main()?)...
So what you need to do is, from that point, loop back to the accept() call so that you can accept another, new client connection. For example, here's some pseudocode:
create server socket
while (1) {
try {
accept client connection
set up your I/O streams
while (1) {
interact with client until connection closes
}
} catch (...) {
handle errors
}
} // loop back to the accept call here
Also, notice how the try-catch block in this case is situated so that errors will be caught and handled within the accept-loop. That way an error on a single client connection will send you back to accept() instead of terminating the server.
Keep a single server socket outside of the loop -- the loop needs to start before accept(). Just put the ServerSocket creation into a separate try/catch block. Otherwise, you'll open a new socket that will try to listen on the same port, but only a single connection has been closed, not the serverSocket. A server socket can accept multiple client connections.
When that works, you probably want to start a new Thread on accept() to support multiple clients. Simplest way to do so is usually to add a "ClinentHandler" class that implements the Runnable interface. And in the client you probably want to put reading from the socket into a separate thread, too.
Is this homework / some kind of assignment?
I have following Socket server's code that reads stream from connected Socket.
try
{
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
int count = 10;
while(count>0)
{
String msg = in.readObject().toString(); //Stucks here if this client is lost.
System.out.println("Client Says : "+msg);
count--;
}
in.close();
client.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
And I have a Client program, that connects with this server, sends some string every second for 10 times, and server reads from the socket for 10 times and prints the message, but if in between I kill the Client program, the Server freezes in between instead of throwing any exception or anything.
How can I detect this freeze condition? and make this loop iterate infinitely and print whatever client sends until connection is active and stable?
The problem is that the server side of the socket has no way of knowing that the client connection closed because the client code terminates without calling .close() on the client side of the socket, and therefore never sends the TCP FIN signal.
One possible way of fixing this would be to create a new Watcher thread that just periodically inspects the socket to see if it is still active. The problem with that approach is that the isConnected() on the Socket will not work for the same reason stated above so the only real way to inspect the connection is to attempt to write to it. However, this may cause random garbage to be sent to a potentially listening client.
Other options would be to implement some type of keep-alive protocol that the client should agree to (i.e., send keep-alive bits every so often so the Watcher has something to look for). You could also just move to the java.nio approach, which I believe does a better job at dealing with these conditions.
This thread is old, but provides more detail: http://www.velocityreviews.com/forums/t541628-sockets-checking-for-dropped-connections-and-close.html.
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.
Before I post this I looked at some past questions on this exceptions but couldn't find an exact answar.
I have a client server app which is basically a socket program connects with TCP.
I got this Exceptions from client side after it runs fine for some time. But still, the client is sending data to the server even though it throws Exceptions.( may be as Event objects are passed continuously). But the server works fine as it receives the data. The Exception I get from the client side while sending data is
java.io.IOException: stream active .. This occurs from the "LINE 01" as mentioned in the code below.
Here is the client code I used.
// And "Event" objects are passed continuously to this method one by one.
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open(new InetSocketAddress(host, port));
oos = new ObjectOutputStream(socketChannel.socket().getOutputStream());
oos.reset(); -----------> LINE 01
oos.writeObject(event);
} catch (IOException e) {
throw new RuntimeException(e);
}
Here is the server code
ServerSocketChannel serverSocketChannel = null;
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(port));
SocketChannel socket = serverSocketChannel.accept();
ObjectInputStream ois = new ObjectInputStream(socket.socket().getInputStream());
do {
Object object = ois.readObject();
if(object instanceof Event) {
Event event = (Event)object ;
viewDetailsInUI(event);
}
} while (true);
Here is the stack trace I got from the client side.
java.io.IOException: stream active
at java.io.ObjectOutputStream.reset(ObjectOutputStream.java:478)
at org.demo.siddhi.server.EventSenderClient.sendEventToSubscriber(EventSenderClient.java:42)
at org.demo.siddhi.server.query.types.SimpleStockQuoteVWAPQueryProvider$3.callBack(SimpleStockQuoteVWAPQueryProvider.java:344)
at org.siddhi.core.OutputStreamHandler.run(OutputStreamHandler.java:61)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Can anyone please explain why is this ?
There are several problems here.
As Peter Lawrey has pointed out, calling reset() immediately you have constructed the ObjectOutputStream is completely pointless, and probably illegal. Remove it.
You are using SocketChannels in blocking mode via streams, i.e. you are just using the underlying Sockets in both cases. You would be much better off using a Socket and a ServerSocket. It's a lot simpler and clearer.
Your server loops reading an ObjectInputStream for multiple objects, but your client creates a new connection, sends one object, and then (I hope) closes it. These do not add up. Either your client should conserve the TCP connection and the ObjectOutputStream and use it to write multiple objects, in which case you may need to call reset() after writeObject(), and the server needs to break out of the loop when it gets EOFException, or your server can close its connection after reading one object, and the while (true) loop is unnecessary.
It appears to believe it is serializing an object already.
IOException if reset() is invoked while serializing an object.
You don't need to call reset() at the start as there is nothing to reset(). I would drop it and it may work fine.
If you want to call reset regularly, you can call it after writeObject().
You should also call flush() somewhere as the stream is buffered.
Look to OOS code:
493 if (depth != 0) {
494 throw new IOException("stream active");
495 }
I need to send and receive alternately byte [] using Socket. How to do this ?
What wrappers to use ?
Is this ok or I can do this on quicker way
public boolean SendMessage(byte[] data){
try{
socket = new Socket(ipAddress, port);
OutputStream socketOutputStream = (OutputStream) socket.getOutputStream();
socketOutputStream.write(data);
socket.close();
return true;
}
catch(Exception exc){
System.err.println(exc.getStackTrace());
}
return false;
}
After call of this function I call function for receiving bytes, and again send =>receive and so on. Is there quicker way to do this ?
Use the same socket for reading and writing, just synchronize the two apps so that one read while the other writes, and vice-versa.
Instead of creating a new socket each time for sending/receiving and then closing it, you should use the same socket.
Say, create two threads. One as the SenderThread and the other as ReceiverThread.
The SenderThread creates a socket and then gets the outputstream and you can have a while loop with a flag to indicate whether it should run or not.
Eg: while (running){
The same thing should be done in the ReceiverThread. Create socket and inputstream. Then run the while loop.
In the while loop, you can provide your logic of writing/reading the data to/from the stream.
Use wait and notify so that the threads run in harmony..