Hanging up in TCP close_wait state

E

eeh

Hi,

I am developing an Ethernet device to interface with a Java
application. The device firstly connects to the Java application
through TCP connection. After sending data, the device would disconnect
actively. However, I find that the Java socket does not respond to the
disconnection by any exception.

I have checked by netstat command that the connection is in a state
CLOSE_WAIT. Then I check the TCP state diagram that in this state the
application should close itself and then send a FIN packet and proceeds
the state to LAST_ACK.

But why the application hangs at the state CLOSE_WAIT?

Is there any way to let it close instantly?

Thanks
 
K

Kevin McMurtrie

eeh said:
Hi,

I am developing an Ethernet device to interface with a Java
application. The device firstly connects to the Java application
through TCP connection. After sending data, the device would disconnect
actively. However, I find that the Java socket does not respond to the
disconnection by any exception.

I have checked by netstat command that the connection is in a state
CLOSE_WAIT. Then I check the TCP state diagram that in this state the
application should close itself and then send a FIN packet and proceeds
the state to LAST_ACK.

But why the application hangs at the state CLOSE_WAIT?

It means that unread data is left in the stream. The connection is
being held open waiting for everything to complete.
Is there any way to let it close instantly?

Socket.setSoLinger()

This isn't really a good solution, though. The connection is reset and
any unread data is lost. The other side may also get into a funky state
if it misses the reset signal. It would be better to finish the streams
so the connection closes normally.
 
E

eeh

However, I find there is no unread data in the stream as the thread
loops to read.

Besides, a key point is that I cannot get exception or signal that the
client side disconnect. I should know when the remote side disconnect
before disconnecting the connection. Actually I expect the
SocketException can trap the signal.

My Java program thread is shown:

class ThreadSS extends Thread
{
Ut ut=new Ut();
App app=new App();
Debug debug=new Debug();

ServerSocket ss;
Component parent;

MyProperties prop;
//InetAddress ia=new InetAddress();
ThreadSS(Component parent,MyProperties prop)
{
this.parent=parent;
this.prop=prop;

try
{
ss=new ServerSocket(0x55);
}
catch(Exception e)
{
app.handleError(parent,e);
return;
}
}

public void run()
{
try
{
while(true)
{

Socket socket=ss.accept();
BufferedInputStream bis=new
BufferedInputStream(socket.getInputStream());

while(true)
{
sleep(1);
int i;
try
{
i=socket.getInputStream().read();

}
catch(SocketException e)
{
break;
}

if(i==-1)
{
}
else
{
debug.println((char)i);
}

}

}
}
catch(Exception e)
{
app.handleError(parent,e);
return;
}
}
}
 
E

Esmond Pitt

Well you said yourself that the application should close the socket and
it is not doing do.

If the read() returns -1 or an EOFException or a SocketException you
should immediately close the socket, it has no further usefulness.

Also, get rid of the pointless sleep() and use Socket.setSoTimeout().
 
K

Kevin McMurtrie

eeh said:
However, I find there is no unread data in the stream as the thread
loops to read.

Besides, a key point is that I cannot get exception or signal that the
client side disconnect. I should know when the remote side disconnect
before disconnecting the connection. Actually I expect the
SocketException can trap the signal.

You need to read up on how Java does I/O and threading. read() is a
blocking call. It blocks, returns data, or returns -1. Your sleep(1)
will destroy the efficiency of your application. When read() returns
-1, the client has gracefully closed its data stream and you have read
the last byte available. It becomes your turn to close your Socket.
You'll never get an Exception unless the client aborts its connection.

See below this -
My Java program thread is shown:

class ThreadSS extends Thread
{
Ut ut=new Ut();
App app=new App();
Debug debug=new Debug();

ServerSocket ss;
Component parent;

MyProperties prop;
//InetAddress ia=new InetAddress();
ThreadSS(Component parent,MyProperties prop)
{
this.parent=parent;
this.prop=prop;

try
{
ss=new ServerSocket(0x55);
}
catch(Exception e)
{
app.handleError(parent,e);
return;
}
}

public void run()
{
try
{
while(true)
{

Socket socket=ss.accept();
BufferedInputStream bis=new
BufferedInputStream(socket.getInputStream());

while(true)
{
sleep(1);
int i;
try
{
i=socket.getInputStream().read();

}
catch(SocketException e)
{
break;
}

if(i==-1)
{
}
else
{
debug.println((char)i);
}

}

}
}
catch(Exception e)
{
app.handleError(parent,e);
return;
}
}
}


This might be more what you want to do. Yeah, it's non-optimal (loss of
exceptions and sucky buffering) but it's a good enough demo.


import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Test
{
protected void serve(ServerSocket ss) throws IOException
{
try
{
while (true)
new HandlerThread(ss.accept());
}
finally
{
ss.close();
}
}


private class HandlerThread extends Thread
{
private final BufferedInputStream m_in;
private final Socket m_socket;

HandlerThread(Socket s) throws IOException
{
m_socket= s;
m_in = new BufferedInputStream(m_socket.getInputStream());
start();
}

public void run()
{
try
{
try
{
int i;
while ((i = m_in.read()) >= 0)
System.out.print((char) i);
}
finally
{
try {m_in.close();} finally {m_socket.close();}
}
}
catch (IOException err)
{
err.printStackTrace();
}
}
}

public static void main (String args[]) throws Exception
{
Test t= new Test();
t.serve (new ServerSocket(8080));
}
}
 
E

eeh

If the read() returns -1 or an EOFException or a SocketException you
should immediately close the socket, it has no further usefulness.

But if I wants the ethernet device to transmit several packets rather
than one, read() would get -1 in between packets. How do I do in this
case?
 
A

Alan Krueger

eeh said:
But if I wants the ethernet device to transmit several packets rather
than one, read() would get -1 in between packets. How do I do in this
case?

Reads on a stream socket don't see packets, they read parts of the
stream. That means a particular read() cannot be guaranteed to be a
distinct packet, it could be parts of one or more.
 
K

Kevin McMurtrie

If the read() returns -1 or an EOFException or a SocketException you
should immediately close the socket, it has no further usefulness.

But if I wants the ethernet device to transmit several packets rather
than one, read() would get -1 in between packets. How do I do in this
case?[/QUOTE]

read() blocks where there's no data. It returns -1 when the stream is
complete and closed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top