I created a server which accept TCP connection . After connected to socket it looping for reading data from input stream.
Steps:
I started my server.
Start Client.
Now I am closing client.
Then Server gives me SocketException Connection Reset
How do I check that my client is alive or not before reading from input stream.
If your server gets a 'connection reset' it is probably writing to a connection that has already been closed by the other end. A browser whose user presses the 'back' button is a good example. If this is an expected condition, ignore the exception. If it constitutes an application protocol error, debug the application.
There are 2 ways you can check if a socket is connected, you can either read or write to it, if it is connected you wont get an error, if it isnt connected you will get an error. This is how i check if a socket is connected:
BufferedReader reader;
public void run()
{
try
{
String message;
while((message = reader.readLine())!=null) //The thread stops here untill the reader has somthing to read
{
System.out.println(message);
}
}catch(Exception e)
{
System.out.println("Client disconnected!");
// an error is thrown when reader cannot read the stream because it is closed, you will get a connection reset error.
}
}
When the Socket is connected the reader waits untill there is somthing to be read(message = reader.readLine()). When the client disconnects and the Socket is closed, the reader throws an exception because there is nothing that can be read because the stream is closed. I hope this helps!
Related
This is my code when I run it in debug mode in eclipse it shows me that it doesn´t continue it stops a stays in the code where I have put an arrow.
private ServerSocket serverSocket = null;
private Socket socket= null;
private ObjectInputStream inputStream= null;
public void ConnectTCP(){
try{
serverSocket = new ServerSocket(5000);
---->socket = serverSocket.accept();
inputStream = new ObjectInputStream(socket.getInputStream());
System.out.print("Server is Running");
}catch(IOException e){
e.printStackTrace();
}
}
Your socket is already created at this line. Because server binds to a port, at the moment ServerSocket constructor is called. As for accept method, due to JavaDoc it
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
A new Socket s is created and, if there is a security manager, the security manager's checkAccept method is called with s.getInetAddress().getHostAddress() and s.getPort() as its arguments to ensure the operation is allowed. This could result in a SecurityException.
So, accept method is just waiting for client connections, that is the reason, why execution stops at this point. May be, it could be helpfull to read a java official tutorial for writing a server side.
Actually it won't stop, it waiting for connection.
When a client want to connect it then it connect with that socket and program flow goes next line.
I am writing an application that streams data that clients can then listen to and receive. However I am running into an issue with closing a socket when a client is no longer listening.
What I do is create a ServerSocket, when then waits for a connection and once it is connected, I start streaming the data. However, once the client is no longer connected, I am stuck in a loop of streaming and cannot tell if anyone is listening. Is there a way around this?
try {
serverSocket = new ServerSocket(STREAM_PORT);
Socket clientSocket = serverSocket.accept();
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream(), true);
while (true) {
pw.println("some data");
}
} catch (SocketException e) {
// Never occurs when client disconnects
} catch (IOException e) {
// Never occurs when client disconnects
}
I have tried using socket.isClosed(), but it always returns false. Am I approaching this from the wrong angle, or is there a way to do it. I would ideally not want the client to have to send the server a "end" command.
EDIT: Edited to reflect what current code I am running after #Rod_Algonquin suggestion
As you are using PrintWriter, which swallows I/O exceptions, you need to call checkError() after each write to see if an error has occurred.
When using NIO, I have the following checks on the server side:
if (key.isReadable()) {
readBuffer.clear();
SocketChannel channel = (SocketChannel) key.channel();
int read = channel.read(readBuffer);
if (read == -1) {
channel.close();
channel.keyFor(selector).cancel();
} else {
readBuffer.flip();
System.out.println(charset.decode(readBuffer));
}
}
However, it is often the case that read will throw java.io.IOException: An existing connection was forcibly closed by the remote host. On the client side, this is what I do to close the connection:
public void close() throws IOException {
connection.close();
connection.keyFor(selector).cancel();
selector.close();
}
If that is not the graceful way, what is?
The server should send a message to the client to close its connection. It can only do this if the buffers are not full, but it will allows the client to gracefully close the connection.
A simpler solution is for the client to expect this exception and handle it silently. However, the poison pill message is more reliable IMHO as you can tell whether the connection was intended to be closed by the server.
BTW The client can send the same message to the server. After sending the message, you might want to wait for the other end to hang up before closing the connection yourself (or timing out)
You get this exception if you have written to the connection after the peer had already closed it. In other words, an application protocol error.
Solution: don't.
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.