22

I would like to write a simple multiplexing server in Clojure (as a sample project to learn the language) but I am having a very hard time finding resources to aid me in this on the web.

does anyone have any resources that can point to the basics of socket programming in Clojure and the best way to go about writing such a server?

horseyguy
  • 29,455
  • 20
  • 103
  • 145

4 Answers4

31

clojure.contrib.server-socket is your friend. Use create-server like so to create a simple echo server:

(import '[java.io BufferedReader InputStreamReader OutputStreamWriter])
(use 'clojure.contrib.server-socket)
(defn echo-server []
  (letfn [(echo [in out]
                    (binding [*in* (BufferedReader. (InputStreamReader. in))
                              *out* (OutputStreamWriter. out)]
                      (loop []
                        (let [input (read-line)]
                          (print input)
                          (flush))
                        (recur))))]
    (create-server 8080 echo)))

(def my-server (echo-server))

Now telnet to make sure it works:

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
hello  // this is the echoed line, woohoo!

By the way, the server is multithreaded too, because clojure.contrib.server-socket creates a new thread on accepting a new connection.

If that doesn't meet your needs, then the Java API is your friend. Since you have full access to Java classes from Clojure, you can just use Java sockets if you need to get down to the metal. I don't know anything about your background, but assuming you have not used Java sockets before, Sun has a tutorial: http://java.sun.com/docs/books/tutorial/networking/sockets/

alanlcode
  • 4,208
  • 3
  • 29
  • 23
  • Thank you! I've created a simple leiningen project for this here with your code: https://github.com/cymen/clojure-socket-echo – Cymen Feb 23 '12 at 22:56
  • 2
    Server-socket now lives in clojars after the breakup of clojure.contrib. https://clojars.org/server-socket is the place to go for Clojure > 1.2. – Justin Leitgeb Dec 28 '12 at 20:08
  • Is this still a good way to go for multithreaded server with concurrent connections? That clojar package hasn't been updated in a while either. I'm also curious how core.async can be integrated.. I'm tempted to make a new question about all of this but want to do my due diligence first – scape Jul 15 '13 at 15:26
  • Nowadays the best bet is probably either `aleph` or `http-kit`, which both use the excellent `ring` server abstraction. – noisesmith Jul 02 '14 at 12:49
10

I wrote a small multiplayer text adventure game called Mire that demonstrates this. It's pretty straightforward.

1

Check out clojure.contrib to see if there are any libraries for manipulating sockets. If there aren't, then you're left with writing your own by using Java classes through Clojure's Java interop facilities.

Pinochle
  • 5,515
  • 2
  • 26
  • 20
0

I wrote a library called clj-sockets that makes it pretty easy. From the README:

(def server (listen (create-server 9871)))
; blocks until a connection is made
; in this case I'm doing "telnet localhost 9871" from the shell
=> #'clj-sockets.core/server

server
=> #<Socket Socket[addr=/0:0:0:0:0:0:0:1%0,port=57437,localport=9871]>

(read-line server)
; blocks until a line is sent (in this case through telnet)
=> "hello from telnet"

(write-line server "hello there, person using telnet!")
=> nil

(close server)
=> nil

It can also help you connect to remote hosts. And there's annotated source code if you want to have a peek under the hood. Good luck!

Alistair
  • 8,066
  • 14
  • 39
  • 43