Excellent John!
This is now working, now I just have to figure out how to copy the input/output streams into separate strings on their way through.
def server = new ServerSocket(8235)
while(true) {
server.accept() { socket ->
socket.withStreams { input, output ->
def s = new Socket("localhost", 9090)
s.withStreams { inStream, outStream ->
try{
blindlyForward(inStream, output,input, outStream)
}catch(Exception e){e.printStackStrace()}
}
}
}
}
public void blindlyForward(InputStream clientInStream, OutputStream serverOutStream, InputStream serverInStream, OutputStream clientOutStream) {
Thread c2s = new Thread(new StreamForwarder(clientInStream,serverOutStream));
StreamForwarder s2c = new StreamForwarder(serverInStream,clientOutStream);
// Run one in a new thread
c2s.start();
// Run the other in this thread
s2c.run();
boolean done = false;
while(!done) {
try {
c2s.join();
done = true;
} catch (InterruptedException e) {
// Shouldn't happen. Thread has no wait() or sleep() calls.
System.out.println(e.getMessage());
}
}
}
> Date: Sat, 13 Mar 2010 13:14:12 +0000
> From: john.hartnup@gmail.com
> To: user@groovy.codehaus.org
> Subject: Re: [groovy-user] Reading from a socket
>
> On 13 March 2010 12:36, Anders Viklund <viklund_anders@hotmail.com> wrote:
> > I guess its the left shift thats causing this problem.
> >
> > But why is the exception thrown for left shift inside the thread and not
> > outside?
>
> I just reproduced it using a simpler case (always a good idea).
>
> When you think it through, it makes sense.
>
> What does withStreams() do?
>
> A1. Get a pair of Input/Output streams from the socket
> A2. Pass the streams to the closure provided as a parameter
> A3. When the closure returns, close the streams (and therefore the socket)
>
> Now, what does your closure do:
> B1. spawns a thread
> B2. returns
>
> ... and within the thread:
> C1. Try to read from the InputStream
> ...
>
> What you're seeing is that A3 happens while C1 is in progress. So C1
> gets the socket closed exception.
>
> To avoid this, you need a wait() for the thread to complete, before
> your withStreams closure returns.
>
> Here's some Java I have lying around. It will probably work as-is
> within Groovy. I see no reason to change it.
>
> public void blindlyForward() {
> Thread c2s = new Thread(new StreamForwarder(clientInStream,serverOutStream));
> StreamForwarder s2c = new StreamForwarder(serverInStream,clientOutStream);
>
> // Run one in a new thread
> c2s.start();
> // Run the other in this thread
> s2c.run();
>
>
> boolean done = false;
> while(!done) {
> try {
> c2s.join();
> done = true;
> } catch (InterruptedException e) {
> // Shouldn't happen. Thread has no wait() or sleep() calls.
> System.out.println(e.getMessage());
> }
> }
> }
>
> ... and StreamForwarder itself:
>
> public class StreamForwarder implements Runnable {
>
> private InputStream input;
> private OutputStream output;
>
> public static final int BLOCKSIZE = 1024;
>
> /**
> * Constructor
> * @param input Something to read from
> * @param output Something to write to
> */
> public StreamForwarder(InputStream input, OutputStream output) {
> this.input = input;
> this.output = output;
> }
>
> /**
> * Run method - read a KB, write a KB, until either an IOException is thrown
> * or we reach EOF.
> */
> public void run() {
> byte[] block = new byte[BLOCKSIZE];
> boolean done = false;
> while(!done) {
> try {
> int size = input.read(block);
> if(size >0) {
> output.write(block,0,size);
> }
> if(size == -1) {
> done = true;
> }
> } catch (IOException e) {
> System.err.println(e.getMessage());
> done = true;
> }
> Thread.yield(); // polite, but surely redundant in this day and age?
> }
> }
> }
>
> --
> "There is no way to peace; peace is the way"
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
> http://xircles.codehaus.org/manage_email
>
>
Hotmail: Free, trusted and rich email service.
Get it now.