Wednesday, 15 May 2013

A TCP Server Haskell Example

Introduction

In today's post, I'll demonstrate (and explain) how to put together a very simple TCP server in Haskell. The most simple example that I can think of, that will still leave you with enough skeleton to get up and running yourself is an echo server.

The Functional Specification

An Echo server. The drab, beige, sensible-older-brother in the server world. We'll accept incoming connections on a port and recite (echo) any data sent to us by the client. Simple.

Design

Using the network, concurrency and system modules in Haskell, you're actually allowed a pretty simple and fluid design. Of course, you can make this as "one-liner" as you'd like, but for demonstration purposes today I'll break the server over a few parts:
  • Main program
  • Socket handler
  • Echo implementation
The main program will take care of getting us out of first gear. It'll setup a listening socket (or server socket) and then hand off client connection responsibilities to the socket handler. The socket handler will then hand the client off to the echo implementation to work with as well as ensure it's ready for any extra connections. Finally, the echo implementation will just facilitate the server's functionality layer in. It will just send back to the client what ever it has given.

Code Walkthrough

The main program is very simple. Setup the server socket using listenOn and then hand control over to the client handler.


The client handler (or socket handler as I called it above) accepts incoming client connections from the server socket using accept. We can then set buffering options (to off) for the client connection with hSetBuffering. From there we make the echo service implementation fire up on a thread of its own with forkIO. forkIO deserves a blog post of its own (as does the Concurrency module as a whole), and it will get one... just not today. Anyway, finally the client handler recurses on itself to handle the next client.

It's a lot of text for some pretty simple code in the end.


Finally, we have the actual implementation. This is the code that makes our server an echo server. We'll take a line of text in from the client socket using hGetLine then we'll write it back to the client using hPutStrLn.


And that's it. The full code listing for this echo server is below.



Final thoughts

There is a fairly basic pattern that you can establish out of the module here that you can adapt for more complex servers of your own. Some further study of the IO system would be needed to develop binary communication protocols of your own, but if you're ok with plain text protocols - this should do just fine!

Enjoy.


2 comments:

  1. The pipes and pipes network libraries are worth a look too. They let you work at a higher level of abstraction which is nice and haskell-ey. Here's a 2-line echo server using them:
    https://gist.github.com/jhickner/5589907

    ReplyDelete
    Replies
    1. That looks really cool - nice and neat and simple. Thanks for the tip!

      Delete