Clojure WebSocket Client
Я настроил сервер WebSocket, используя http-kit, который должен принимать подключения через веб-сокет. Это основной пример, показанный в документации http-kit.
Вопрос в том, как создать клиент Clojure, который подключается к нему?
Клиент может быть любой http-библиотекой Clojure, я не против. Я уже знаю о клиентах Javascript и считаю, что у Java есть API, который я мог бы использовать из Clojure. Но я ищу библиотеку Clojure, которая поддерживает веб-сокеты как для клиента, так и для сервера. Я не увидел в коде http-kit ничего, что могло бы облегчить процесс.
6 ответов
У aleph есть поддержка веб-сокетов как на сервере, так и на клиенте. Может потребоваться некоторое время, чтобы привыкнуть к асинхронному стилю и основным абстракциям aleph, но это очень хороший инструмент, когда вы освоите его.
Клиент http-kit пока не поддерживает WebSocket (я не могу придумать хороший API для него). Aleph - хороший вариант для такого случая использования. Другой вариант - http.async.client, я использовал его в модульном тесте websocket сервера http-kit: здесь
Для тех, кто присоединился к нам в 2015 году: будучи новичком в этом, я потратил некоторое время на то, чтобы опробовать все доступные варианты, и было довольно сложно найти библиотеку, которая обеспечивает простой способ установки простого клиента Clojure WebSocket. (Честно говоря, кажется, что клиент WebSocket не очень часто работает в контексте, не связанном с браузером /JavaScript, и поэтому так много внимания уделяется клиентам ClojureScript WebSocket.)
Хотя это не очень хорошо задокументировано, https://github.com/cch1/http.async.client оказался для меня путем наименьшего сопротивления. Мне удалось успешно прочитать потоковые данные с сервера WebSocket и распечатать их на консоли, выполнив следующие действия:
(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))
Бесконечный цикл в конце - просто чтобы не допустить окончания процесса. Пока я не нажму Ctrl-C, сообщения, полученные из сокета, печатаются в STDOUT.
Согласно этому объявлению, http-kit поддерживает веб-сокеты. Если вы не привязаны к асинхронным средствам, которые предлагает клиент http-kit, вы также можете использовать clj-http. Кажется, у них очень похожий интерфейс (я пользуюсь, но пока нет clj-http).
(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!")
Я построил базовый клиент и сервер websocket, он использует java-сокеты и оборачивает фреймы websocket. Он уникален тем, что сервер может одновременно принимать как обычные сокет-соединения, так и веб-сокеты.
http://github.com/viperscape/gulfstream
Пример кода клиента:
(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))