s.withStreams { inStream, outStream ->
def reader = inStream.newReader()
def name = reader.readLine()
outStream << "Hello ${name}"
}
... one of my favourite examples of closures leading to neat idioms.
--
"There is no way to peace; peace is the way"
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
Basically, I don't think the Socket.leftShift() function does what you
want, with an inputStream as an argument.
Instead I think you need a loop that reads from input and writes to s.
Ah, I was going by the JavaDoc for Socket, which doesn't really
specify what leftShift(Object) does in detail:
"Overloads the left shift operator to provide an append mechanism to
add things to the output stream of a socket"
That doesn't document the fairly specialised case of an InputStream.
Could do better!
Without any documented semantics for leftShift(InputStream), I don't
know what you're trying to do, nor whether it should work.
Does the InputStream eventually signal EOF? It would seem reasonable
for leftShift() to return only when that happens. But again, nothing
*says* that it will. At least not in the JavaDoc.
And how would it know to stop reading from the inputstream, unless you
call a method that
So, do a loop. It's only using Java stuff; no Groovy tricks, but it's
simple and it works.
byte[] buffer
def len = input.read(buffer)
while(len >=0) {
output.write(buffer,0,len)
len = input.read(buffer)
}
Of course you probably also want to do the same to transmit data in
the opposite direction. You could do this in another thread:
// Wrap the code above in a StreamForwarder class that implements Runnable.
Thread c2s = new Thread(new StreamForwarder(clientInStream,serverOutStream));
StreamForwarder s2c = new StreamForwarder(serverInStream,clientOutStream);
// Run one in a new thread
2s.start();
// Run the other in this thread
s2c.run();
Or you could read up on select() and do it all in one thread.
Potentially better scalability. Arguably less easy for people to
understand, if they later read the code and are not familiar with
select().
> def len = input.read(buffer) // <-- now its stalling here, why?
http://java.sun.com/j2se/1.4.2/docs/api/java/io/InputStream.html#read(byte[])
"This method blocks until input data is available, end of file is
detected, or an exception is thrown."
So, it's waiting for the other end to either write to the socket, or close it.
It seems as if by trying to write a proxy, you're running before you
can walk. Go through the Java sockets tutorials.
http://java.sun.com/docs/books/tutorial/networking/sockets/index.html
Write a simple client/server pair and make sure you understand how it works.
Groovy doesn't change anything much, other than give you a few
convenience methods for common cases (such as
ServerSocket.accept(Closure ) and Socket.withStreams(Closure)
Because one of your sockets is closed. Since you've bundled the read
and the write into one statement, and you've thrown away the stack
trace, it's not possible to tell which one. Either the client has
closed the socket you're reading from, or the server has closed the
socket you're writing to. Your code is going to have to deal with
that, and it cannot assume that they'll happen in a particular order.
Use e.printStackTrace(), and stop desperately clinging onto your
desire to use '<<', since nobody who's prepared to comment at this
time, knows how it's supposed to behave.
I don't understand why you didn't see this exception until you
explicitly caught it. Are you working in some wider environment that
catches and ignores exceptions? Or did you just fail to tell us about
the exceptions when they were reported?
I would like to allocate more memory for running groovy.
Is it by changing the JAVA_OPTS?
I have changed the groovy/bin/startGroovy.bat file, placing the command:
set JAVA_OPTS="-Xmx512m" But the resource monitor tells that only 55M is allocated to groovy when it's running in windows.
Is there any other place that I should make change in order to allocate more memory for running groovy?
Thanks!
Hix
|
|
> java.net.SocketException: socket closed
> at java.net.SocketInputStream.socketRead0(Native Method)
> at java.net.SocketInputStream.read(SocketInputStream.java:129)
> at org.codehaus.groovy.runtime.DefaultGroovyMethods.leftShift(DefaultGroovyMethods.java:5011)
Which of your two sockets do you think that applies to (there is
enough info there to tell)
What do you think the state of that socket is when the read happens?
(the exception message tells you)
How do you want your proxy to behave when that state occurs? (this is
your implementation decision)
Note: "less code" is great, but only if it does what you need it to!
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?
I checked the link you mentioned. Yes, Xms is for the max memory capacity, not the running memory. Any way to specify the running memory?
|
I see then. My program is not out of memory, but it's slow. So I am thinking of increase the memory capacity for the program to see if it would make it faster.
:(
Hix
|
Unfortunately, it's under windows vista.
:(
Actually I am considering changing to linux like ubuntu as an alternative if things can't be speed up in windows. |
2. Prepare builder component files that can be mixed and matched into
a larger container builder.
I would like to be able to include external builders and have my
builder subclass read-in the external files and process the nodes as
if they were resident.
Any direction would be appreciated
Thanks Victor
I agree the speeding up the program is not a simple memory issue. Actually it is not a simple issue at all.
I am using groovy as front end and MS Access as database backend (in the same machine, not with network yet) to run for a simulation on the artificial financial market that involves with quite a lot of interactions among objects and data extracting from database. I am working on my economics thesis, and I am not familiar with the inside structure of the computer and complier, etc.
I was guessing the bottomneck is in the database visiting. So I have switched the database backend from MS Access to MySQL, however, it does not help in speeding up the program. Just my experience. |
You'd have to put some logic around the write to the outputstream, to
catch the IOException and do what you want to do (ignore it?)
Work with an HTTP library, rather than at the socket level?
Or write your own - perhaps having studied the source for one of the
existing ones.
One way is to run inside Jetty.
Well, Jetty's tiny, so it doesn't feel like overkill to me.
Other alternatives... Observer pattern?
If Jetty seems too heavyweight for you, why not extract just the HTTP
"server" aspect of it ?
I remember there was a book sometime ago that explained how Tomcat worked.
Maybe that would help you pick out bits for Tomcat (or Jetty) ?
However, I do get the impression that you are a little out of your depth
here.
GTG
>> However, I do get the impression that you are a little out of your
>> depth here.
> I agree with you, it would be good enough if I could change this code
> some how to find start/end of the http request, without closing the
> stream in between.
Have you read up on the HTTP protocol ? The first few hits from google
aren't that bad...
Dead end 'cause no-one can give you a 10-line snippet of code on how to do
it ? Yes.
Why has no-one given you a 10-line snipped of code to parse HTTP ?
Probably 'cause none exists.
You have two choices:
1) Write your own HTTP parsing code.
2) Re-use someone elses.
Why don't you want to re-use someone else's ?
Why have you discounted, for example, the top google hit for "java http
server" ?
Did you google something like "java http server" ?
I guess I will have to start reading up on how the java http server works, maybe here
http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/index.html
or here?
http://api.dpml.net/jetty/5.1.6/
Thanks for any further ideas!