Wednesday, April 28, 2010

Groovy Sockets example

I found several sites and blogs with Groovy socket examples but none that showed a matched pair of the server and the client sending data back and forth. Collecting bits from different sources, I put together the following server and client scripts using Groovy.

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...

5 comments:

  1. 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.

    ReplyDelete
  2. Kris,

    Here'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;
    }

    ReplyDelete
  3. 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.

    ReplyDelete
  4. Not 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.

    Server 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"
    }

    ReplyDelete
  5. Thank you so much. It really helped me, a groovy starter.

    ReplyDelete