19

I have set up a WebSocket server using http-kit that should accept web socket connections. It is the basic example shown in the http-kit documentation.

The question is: How do you create a Clojure client that connects to it?

The client can be any Clojure http library, I don't really mind. I already know about Javascript clients, and I believe that Java has an API that I could use from Clojure. But what I am looking for is a Clojure library that supports websockets both for client and server. I saw nothing in http-kit code that would make it easy.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
user2263578
  • 215
  • 2
  • 9
  • do you want to use a Clojure websocket client just to make things simpler? A non-web-based client is not really the use case for websockets, which explains the lack of a Clojure client. However if you Google for Java websocket clients it looks like you'll find a few, then perhaps you can use interop to set up the Java client in Clojure. . – georgek May 08 '13 at 22:20
  • I know it is not the usual use case. I saw the java ones, I just want to know if that is possible in Clojure with an existing library. It looks like it shoud be, since http clients do exist. – user2263578 May 08 '13 at 22:31

6 Answers6

11

aleph has support for websockets on both server and client. It can take some time to get used to the asynchronous style and aleph's core abstractions, but it's a very good tool once you get the hang of it.

MasterMastic
  • 20,711
  • 12
  • 68
  • 90
amalloy
  • 89,153
  • 8
  • 140
  • 205
  • Found it, thanks. I had previously ruled it out because the function names were weird, but it was obviously a mistake. – user2263578 May 08 '13 at 22:39
9

http-kit's client does not support WebSocket yet(I can't think of a good API for it). Aleph is a good option for this kind of use case. Another option is http.async.client, I've used it in http-kit's server's websocket unit test: here

Lrrr
  • 4,755
  • 5
  • 41
  • 63
shenedu
  • 1,161
  • 1
  • 7
  • 4
9

Gniazdo is a WebSocket client for Clojure. It wraps the Jetty's implementation of the protocol.

Jan
  • 11,636
  • 38
  • 47
8

For those joining us in 2015: being new to this, I just spent a while trying out all the different options available, and it was pretty difficult to find a library that provides an easy way to set up a simple Clojure WebSocket client. (To be fair, it seems like it's not very common for a WebSocket client to be running in a non-browser/JavaScript context, which is why there seems to be so much emphasis on ClojureScript WebSocket clients.)

Although it is not well-documented, http.async.client ended up being the path of least resistance for me. I was able to successfully read streaming data from a WebSocket server and print it to the console by doing this:

(ns example.core
  (:require [http.async.client :as async]))

(def url "ws://localhost:1337")

(defn on-open [ws]
  (println "Connected to WebSocket."))

(defn on-close [ws code reason]
  (println "Connection to WebSocket closed.\n"
           (format "(Code %s, reason: %s)" code reason)))

(defn on-error [ws e]
  (println "ERROR:" e))

(defn handle-message [ws msg]
  (prn "got message:" msg))

(defn -main []
  (println "Connecting...")
  (-> (async/create-client)
      (async/websocket url
                       :open  on-open
                       :close on-close
                       :error on-error
                       :text  handle-message
                       :byte  handle-message))
  ;; Avoid exiting until the process is interrupted.
  (while true))

The infinite loop at the end is just to keep the process from ending. Until I press Ctrl-C, messages received from the socket are printed to STDOUT.

Dave Yarwood
  • 2,866
  • 1
  • 17
  • 29
  • 2
    for an [http-kit version](https://www.http-kit.org/server.html#channel) that works really well out of the box there's a really nice example of [a chat app](https://github.com/http-kit/chat-websocket) although for those of us joining in 2019 you'll need to update all the libraries since some dependecies of their example have been deprecated in java 11. I forked it [here](https://github.com/cycle337/chat-websocket) and done just that for you. You'll still need to keep the inifinte loop for it not to close -- add it in the chat-handler. – Vlad A. Dec 05 '19 at 06:45
  • 1
    correct way is to set nginx to keep websockets open for as many seconds as you want. – Vlad A. Dec 05 '19 at 18:36
  • 1
    an even better way is to use a constant ping function to keep the connection alive. – Vlad A. Dec 17 '19 at 01:02
7

According to this announcement, http-kit has support for web sockets. If you're not bound to the asynchronous facilities that http-kit client offer, you could also use clj-http. They have a very similar interface, it seems (I have use but clj-http yet).


(ns playground.experiments.ws
  (:use aleph.http lamina.core))

(defn ws-client [] (websocket-client {:url "ws://echo.websocket.org:80"}))

(defn echo [message]
  (let [channel (wait-for-result (ws-client) 500)]
    (enqueue channel message)
      (let [echo (wait-for-result (read-channel channel) 500)]
        (close channel)
        echo)))

(echo "Echo me!")
i-blis
  • 3,149
  • 24
  • 31
  • I saw tha already. It has support for server, but I can't find a way to create a http-kit client that will connect to my server (there might be something obvious I missed). Asynchronous would be nice, but not necessary for now. Have you ever connected to a server with clj-http? Or only the other way round? – user2263578 May 08 '13 at 21:49
  • I connected to localhost (and pulled data from web apis), don't remember any issues. Disclaimer: I have little experience with Clojure so far, merely experiments with the tool set. – i-blis May 08 '13 at 22:01
  • That is just what I am looking for... For some reason I can't find out how to create a client in the doc. Can you point me to an example? – user2263578 May 08 '13 at 22:27
  • @user2263578 Added a code example, although you certainly found your way through. And yes, it uses aleph. My mistake. – i-blis May 09 '13 at 01:22
1

I built a basic websocket client and server, it uses java sockets and wraps websocket frames. It's unique in that the server can accept both regular socket connections as well as websockets, simultaneously.

http://github.com/viperscape/gulfstream

Example client code:

(def clienthandler
  (with-conn server
    (send! server "i'm here!")
    (with-data server data (prn "client received" data))
    (prn "client is now disconnected")))

(def ws-conn-details {:host "ws://echo.websocket.org/chat",:handler clienthandler})

(def client-conn (start-client ws-conn-details))
scape
  • 652
  • 12
  • 27