Networking with GIO

These examples demonstrate the networking functionality that has recently landed in GLib as official part of GIO.

You will need GLib version >= 2.22 (Check with pkg-config glib-2.0 --modversion) and Vala >= 0.11.0

Synchronous Client Example

void main () {
    var host = "www.google.com";

    try {
        // Resolve hostname to IP address
        var resolver = Resolver.get_default ();
        var addresses = resolver.lookup_by_name (host, null);
        var address = addresses.nth_data (0);
        print (@"Resolved $host to $address\n");

        // Connect
        var client = new SocketClient ();
        var conn = client.connect (new InetSocketAddress (address, 80));
        print (@"Connected to $host\n");

        // Send HTTP GET request
        var message = @"GET / HTTP/1.1\r\nHost: $host\r\n\r\n";
        conn.output_stream.write (message.data);
        print ("Wrote request\n");

        // Receive response
        var response = new DataInputStream (conn.input_stream);
        var status_line = response.read_line (null).strip ();
        print ("Received status line: %s\n", status_line);

    } catch (Error e) {
        stderr.printf ("%s\n", e.message);
    }
}

Compile and Run

$ valac --pkg gio-2.0 gio-network-client.vala
$ ./gio-network-client

Asynchronous Client Example

class AsyncDemo {

    private MainLoop loop;

    public AsyncDemo (MainLoop loop) {
        this.loop = loop;
    }

    public async void http_request () throws Error {
        try {
            var resolver = Resolver.get_default ();
            var addresses = yield resolver.lookup_by_name_async ("www.google.com");
            var address = addresses.nth_data (0);
            print ("(async) resolved www.google.com to %s\n", address.to_string ());

            var socket_address = new InetSocketAddress (address, 80);
            var client = new SocketClient ();
            var conn = yield client.connect_async (socket_address);
            print ("(async) connected to www.google.com\n");

            var message = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
            yield conn.output_stream.write_async (message.data, Priority.DEFAULT);
            print ("(async) wrote request\n");

            // we set the socket back to blocking here for the convenience
            // of DataInputStream
            conn.socket.set_blocking (true);

            var input = new DataInputStream (conn.input_stream);
            message = input.read_line (null).strip ();
            print ("(async) received status line: %s\n", message);
        } catch (Error e) {
            stderr.printf ("%s\n", e.message);
        }

        this.loop.quit ();
    }
}

void main () {
    var loop = new MainLoop ();
    var demo = new AsyncDemo (loop);
    demo.http_request.begin ();
    loop.run ();
}

Compile and Run

$ valac --pkg gio-2.0 gio-network-client-async.vala
$ ./gio-network-client-async

Server Example

void process_request (InputStream input, OutputStream output) throws Error {
    var data_in = new DataInputStream (input);
    string line;
    while ((line = data_in.read_line (null)) != null) {
        stdout.printf ("%s\n", line);
        if (line.strip () == "") break;
    }

    string content = "<html><h1>Hello from Vala server</h1></html>";
    var header = new StringBuilder ();
    header.append ("HTTP/1.0 200 OK\r\n");
    header.append ("Content-Type: text/html\r\n");
    header.append_printf ("Content-Length: %lu\r\n\r\n", content.length);

    output.write (header.str.data);
    output.write (content.data);
    output.flush ();
}

int main () {
    try {
        var service = new SocketService ();
        service.add_inet_port (8080, null);
        service.start ();
        while (true) {
            var conn = service.accept (null);
            process_request (conn.input_stream, conn.output_stream);
        }
    } catch (Error e) {
        stderr.printf ("%s\n", e.message);
    }
    return 0;
}

Compile and Run

$ valac --pkg gio-2.0 gio-server.vala
$ ./gio-server

Enter http://localhost:8080/ in your browser address bar.

Asynchronous Server Example

bool on_incoming_connection (SocketConnection conn) {
    stdout.printf ("Got incoming connection\n");
    // Process the request asynchronously
    process_request.begin (conn);
    return true;
}

async void process_request (SocketConnection conn) {
    try {
        var dis = new DataInputStream (conn.input_stream);
        var dos = new DataOutputStream (conn.output_stream);
        string req = yield dis.read_line_async (Priority.HIGH_IDLE);
        dos.put_string ("Got: %s\n".printf (req));
    } catch (Error e) {
        stderr.printf ("%s\n", e.message);
    }
}

void main () {
    try {
        var srv = new SocketService ();
        srv.add_inet_port (3333, null);
        srv.incoming.connect (on_incoming_connection);
        srv.start ();
        new MainLoop ().run ();
    } catch (Error e) {
        stderr.printf ("%s\n", e.message);
    }
}

Compile and Run

$ valac --pkg gio-2.0 gio-server-async.vala
$ ./gio-server-async

Connect to localhost via netcat or telnet on port 3333 and issue a command ending with a newline.  echo "blub" | nc localhost 3333 

UDP Server example

int main () {
    try {

        var socket = new Socket (SocketFamily.IPV4,
                                 SocketType.DATAGRAM, 
                                 SocketProtocol.UDP);
        var sa = new InetSocketAddress (new InetAddress.loopback (SocketFamily.IPV4),
                                        3333);
        socket.bind (sa, true);

        var source = socket.create_source (IOCondition.IN);
        source.set_callback ((s, cond) => {
            try {
                uint8 buffer[4096];
                size_t read = s.receive (buffer);
                buffer[read] = 0; // null-terminate string
                print ("Got %ld bytes of data: %s", (long) read, (string) buffer);
            } catch (Error e) {
                stderr.printf (e.message);
            }
            return true;
        });
        source.attach (MainContext.default ());

        new MainLoop ().run ();
        
    } catch (Error e) {
        stderr.printf (e.message);
        return 1;
    }
    
    return 0;
}

Compile and Run

$ valac --pkg gio-2.0 gio-udp-demo.vala
$ ./gio-udp-demo

Send some data to localhost via netcat on port 3333.  echo "blub" | nc -u 127.0.0.1 3333 


Vala/Examples

Projects/Vala/GIONetworkingSample (last edited 2013-11-22 16:48:26 by WilliamJonMcCann)