The sample works by sending a line of data as a request; thus the server calls readLine() and the client sends a new line character at the end of the input. The server echos the request back to the client along with a timestamp. For those that skip reading the documentation, ServerSocket's accept method "Accepts a connection and passes the resulting Socket to the closure which runs in a new Thread." so this server creates a new thread for each request.
Groovy Socket server
import java.net.ServerSocket def server = new ServerSocket(4444) while(true) { server.accept { socket -> println "processing new connection..." socket.withStreams { input, output -> def reader = input.newReader() def buffer = reader.readLine() println "server received: $buffer" now = new Date() output << "echo-response($now): " + buffer + "\n" } println "processing/thread complete." } }Groovy Socket client
s = new Socket("localhost", 4444); s.withStreams { input, output -> output << "echo testing ...\n" buffer = input.newReader().readLine() println "response = $buffer" }
Give it try! Hope this helps...
ServerSocket's accept returns a plain JDK based socket. So how does withStreams work with plain JDK based socket or is it a groovy based socket class enhanced with withStreams method that takes c closure. Thanks for the post.
ReplyDeleteKris,
ReplyDeleteHere's a copy of the accept method from the GDK taken out of Groovy 1.7.2. As you can see from the code - the GDK class does get a Socket returned but then it calls the closure within a thread using the Socket it was returned. Sorry, maybe my description wasn't completely clear but you can see more from the code - which is in DefaultGroovyMethods.java in the GDK.
/**
* Accepts a connection and passes the resulting Socket to the closure
* which runs in a new Thread.
*
* @param serverSocket a ServerSocket
* @param closure a Closure
* @return a Socket
* @throws IOException if an IOException occurs.
* @see java.net.ServerSocket#accept()
* @since 1.0
*/
public static Socket accept(ServerSocket serverSocket, final Closure closure) throws IOException {
final Socket socket = serverSocket.accept();
new Thread(new Runnable() {
public void run() {
try {
closure.call(socket);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
LOG.warning("Caught exception closing socket: " + e);
}
}
}
}
}).start();
return socket;
}
Have you tried reading multiple lines on the server side until end of stream? I tried and the readLine call never returns null for end of stream. It just hangs.
ReplyDeleteNot sure if this matches what you tried, but I adjusted the code a bit to send mutliple lines and did call readLine until it returned null.
ReplyDeleteServer code
import java.net.ServerSocket
def server = new ServerSocket(4242)
while(true) {
server.accept { socket ->
println "processing new connection..."
socket.withStreams { input, output ->
def reader = input.newReader()
def buffer = null
while ((buffer = reader.readLine()) != null) {
//def buffer = reader.readLine()
println "server received: $buffer"
if (buffer == "*bye*") {
println "exiting..."
System.exit(0)
} else {
output << "echo-response: " + buffer + "\n"
}
}
}
println "processing complete."
}
}
Client side
s = new Socket("localhost", 4242);
s.withStreams { input, output ->
output << "echo line 1\n"
output << "echo line 2\n"
output << "echo line 3\n"
output << "echo line 4\n"
//output << "*bye*\n"
reader = input.newReader()
buffer = reader.readLine()
println "response = $buffer"
}
Thank you so much. It really helped me, a groovy starter.
ReplyDelete