Timeout question on a socket thread

R

RVic

I have a thread that listens for a socket conection (and once the
connection is made, creates another thread to listen for another
connection, the former thread continues on to process the request). My
run() method is shown below (annotated for brevity).

I need to implement a timeout function between the time the connection
is established and the time it reads receives data (not the same thing
as ServerSocket.setSoTimeout() -- which is also implemented here btw.
Rather, I need to also herein put a maximum time limit it will wait
between the time the connection is establised and it receives a stream
of data).

My thoughts on how to implement this are with a timer. However, within
my run() method, I have a finally block necessary for cleanup. Thus,
if I am going to return from run(), I want to make sure to perform the
same cleanup. However, when I attempt this, inside the ActionListener
inside my timer, I get errors like:

"Cannot refer to a non-final variable inputBuffered inside an inner
class defined in a different method"

Can anyone see a different (likely better) way around my dilemma here?
Thanks. RV

public void run() {
Socket socket = null;
try {
socket = this.server.accept();
}
catch (IOException e) { }
BufferedInputStream inputBuffered = null;
OutputStream output = null;
StringBuilder request = null;
try {
inputBuffered = new BufferedInputStream(socket.getInputStream
());
output = socket.getOutputStream();
if (!socket.isClosed()) {
byte inputRead[] = new byte[4096];
String response = null;
Timer timer1 = new Timer(this.inactivityTimeOut * 1000, new
java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
try {
if (null != socket) {
socket.close();
}
if (null != inputBuffered) {
inputBuffered.close();
}
if (null != output) {
output.close();
}
}
catch (Exception e) {
stackLog.error(e, e);
}
return;
}
});
int bytesRead;

while (0 <= (bytesRead = inputBuffered.read(inputRead, 0,
4096))) {
...
} // END WHILE reading from client
}
}
catch (Exception e) {

}
finally {
try {
if (null != socket) {
socket.close();
}
if (null != inputBuffered) {
inputBuffered.close();
}
if (null != output) {
output.close();
}
}
catch (Exception e) {
stackLog.error(e, e);
}
}
}
}
 
R

RVic

But say I declare something as final, and initialize it to null in the
declaration (so I can access it in y finally block), can I
subsequently assign it
final OutputStream output = null;
try {
output = socket.getOutputStream(); //is this legitimate?
}finally{
output = null; //is this legitimate?
 
R

RVic

I dont think there is any way around this. I have two timers I need to
implement on the socket, one is a maximum connect time, another is the
max wait time between getting bytes from the client.

It;s the latter that I need to rethink how to handle here. I don;t
know if I can do it with a timer class frankly, or if there is not a
better implementation.
 
D

Donkey Hottie

RVic said:
But say I declare something as final, and initialize it
to null in the declaration (so I can access it in y
finally block), can I subsequently assign it
final OutputStream output = null;
try {
output = socket.getOutputStream(); //is this
legitimate? }finally{
output = null; //is this
legitimate?

No, those are not legitimate.

Never assign it null, and never assume it might be null.
 
K

Knute Johnson

RVic said:
I have a thread that listens for a socket conection (and once the
connection is made, creates another thread to listen for another
connection, the former thread continues on to process the request). My
run() method is shown below (annotated for brevity).

I need to implement a timeout function between the time the connection
is established and the time it reads receives data (not the same thing
as ServerSocket.setSoTimeout() -- which is also implemented here btw.
Rather, I need to also herein put a maximum time limit it will wait
between the time the connection is establised and it receives a stream
of data).

My thoughts on how to implement this are with a timer. However, within
my run() method, I have a finally block necessary for cleanup. Thus,
if I am going to return from run(), I want to make sure to perform the
same cleanup. However, when I attempt this, inside the ActionListener
inside my timer, I get errors like:

Just set the timeout on the Socket returned when you do the
ServerSocket.accept(). If you don't receive any data by the timeout it
will throw a SocketException. This will have no effect on the ServerSocket.
 
R

RVic

My problem is more complicated than I thought. Again, my class is
annotated -- BUT, in run() I need to let it go for a maximim of
maxConnectedTime seconds. If that is exceeded, I need to clean up,
kill this thing. So I create a timer, and an ActionListener to go off
if maxConnectedTime seconds is exceeded. However, I am painted into a
corner and don;t know how to get out! I need to:
1. Be sure I can exit not only the ActionListener method inside the
Timer here, but the entire run() method, i.e. shut this thread down.
2. My cleanup really occurs in the finally block at the end of run().
I cannot simply put that into my ActionListener because of variable
restrictions (i.e. my variables are not final, and if I make surrogate
final variables per Eric's suggestion, I don't know what they are yet,
cannot even declare them.

If there was a way I could force an exception back out to run(), I
could get out of this nice and cleanly when the time was up. But it
seems that connot be done.

How do I get out of this corner?

public class SocketListener implements Runnable {

public void start() throws Exception {
try {
this.server = new ServerSocket(this.port, this.backlog,
this.bindAddress);
this.server.setSoTimeout(this.inactivityTimeOut * 1000);
listen();
}catch(Exception e){}

public void listen() {
this.threadPool.getInstance().run(this);
}

public void run() {
Timer timer1 = new Timer(this.maxConnectedTime * 1000,
new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e)
{
//we need to check on cleanup like in finally at end here
//additionally, we need to get out of here altogether
//not just return from this actionPerformed, but from the
//enclosing run()
}
});
timer1.start();
// Accept a connection
Socket socket = null;
try {
socket = this.server.accept();
}
catch (IOException e) {
}

// Create a new thread to accept the next connection
listen();

// CONSIDER: non-buffered readers/writers
BufferedInputStream inputBuffered = null;
OutputStream output = null;
StringBuilder request = null;
try {
inputBuffered = new BufferedInputStream(socket.getInputStream
());
output = socket.getOutputStream();
if (!socket.isClosed()) {
byte inputRead[] = new byte[4096];
int bytesRead;
while (0 <= (bytesRead = inputBuffered.read(inputRead, 0,
4096))) {
..............
} // END WHILE reading from client
}
}
catch (SocketException se) {

}
catch (Exception e) {

}
finally {
try {
if (timer1 != null) {
timer1.stop();
}
if (null != socket) {
log.info("Closing connection, cleaning up");
socket.close();
}
if (null != inputBuffered) {
inputBuffered.close();
}
if (null != output) {
output.close();
}
}
catch (Exception e) {
stackLog.error(e, e);
}
}
}
}
 
L

Lew

But say I declare something as final, and initialize it to null in the
declaration (so I can access it in y finally block), can I
subsequently assign it
final OutputStream output = null;
    try {
      output = socket.getOutputStream(); //is this legitimate?}finally{

     output = null;                      //is this legitimate?

No, it is not legitimate. So don't assign 'null' to 'output'.

That makes the lifetime of 'output' exactly that of the instance of
which it's a member.

This is a good thing.

Here's one of several ways to use such a thing:

public class Foo
{
...
public void doSomething()
{
final OutputStream output;
try
{
output = socket.getOutputStream();
}
catch ( IOException exc )
{
logger.error( "Cannot open output stream" );
return;
}
Runnable task = new Runnable()
{
@Override public void run()
{
byte [] inputBuf = new byte [BUFSIZE];
try
{
for ( int bRead;
(bRead = inputBuffered.read( inputBuf )) >= 0;
)
{
output.write( inputBuf. 0, bRead );
}
}
catch ( IOException ioe )
{
logger.error( "Cannot write to output" );
}
}
};
try
{
Thread tt = new Thread( task );
tt.start();
...
tt.join();
}
finally
{
try
{
output.close();
}
catch ( IOException ioe )
{
logger.error( "Cannot close stream" );
}
}
...

This is obviously incomplete and untested, but it should give the
idea.
 
R

RVic

But a Timer runs in its own thread, right? So Can't I create something
that uses

Thread.currentThread().interrupt();

to force my running thread to finish up and finalize?
 
K

Knute Johnson

RVic said:
My problem is more complicated than I thought. Again, my class is
annotated -- BUT, in run() I need to let it go for a maximim of
maxConnectedTime seconds. If that is exceeded, I need to clean up,
kill this thing. So I create a timer, and an ActionListener to go off
if maxConnectedTime seconds is exceeded. However, I am painted into a
corner and don;t know how to get out! I need to:
1. Be sure I can exit not only the ActionListener method inside the
Timer here, but the entire run() method, i.e. shut this thread down.
2. My cleanup really occurs in the finally block at the end of run().
I cannot simply put that into my ActionListener because of variable
restrictions (i.e. my variables are not final, and if I make surrogate
final variables per Eric's suggestion, I don't know what they are yet,
cannot even declare them.

If there was a way I could force an exception back out to run(), I
could get out of this nice and cleanly when the time was up. But it
seems that connot be done.

How do I get out of this corner?

You are missing the point completely. The simplest way to construct the
server is to have one thread that loops on the ServerSocket. Once you
accept a connection, do the I/O on another thread until you've read
everything or it times out. If it times out, clean up and the leave the
thread. You don't need timers or anything else it's already there. You
can adjust the timeout anytime you aren't blocked. So if you want a
short timeout on the login and a longer timeout on the main I/O thread
you can.


Pseudo code (and it's missing a lot of stuff)

class Server extends Runnable {
public void run() {
while (true) {
try {
Socket s = serverSocket.accept();
Server Task task = new ServerTask(s);
new Thread(task).start();
} catch ( ) {
}
}
}

class ServerTask implements Runnable {
final Socket s;

public ServerTask(Socket s) {
this.s = s;
s.setSoTimeout(20000); // 20 sec timeout
}

public void run() {
try {
while (!endOfStream, true or some other test) {
// read from stream
}
} catch ( ) {
// log errors
} finally {
// clean up
}
}
}

If your time out needs to happen even if there is data coming in then
just close the socket. Add this to the constructor of the ServerTask
(also in pseudo code).

java.util.Timer timer = new java.util.Timer();
timer.schedule(new TimerTask() {
public void run() {
try {
s.close();
} catch ( ) { }
}
},delay);
 
D

Daniel Pitts

RVic said:
But say I declare something as final, and initialize it to null in the
declaration (so I can access it in y finally block), can I
subsequently assign it
final OutputStream output = null;
try {
output = socket.getOutputStream(); //is this legitimate?
}finally{
output = null; //is this legitimate?
This will *always* set output = null, even if socket.getOutput() succeeded.

What you probably want to do is:
OutputStream output = null;
try {
output = socket.getOutputStream();
final OutputStream innerOutput = output;
// Use innerOutput.
} finally {
if (output != null)
output.close();
}

OR you can use a non-anonymous class instead.
 
R

Roedy Green

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,068
Latest member
MakersCBDIngredients

Latest Threads

Top