Веб-сокеты могут показаться пугающими, но если вы используете Clojure и jQuery, это на самом деле довольно просто.
Первое, что вам нужно сделать, это захватить сервер с поддержкой WebSocket. Jetty — неплохой вариант, но (недавно выпущенный Джо Уолнесом) webbit был самым быстрым выбором для начала работы.
Вы, вероятно, захотите:
git clone https://github.com/joewalnes/webbit.git
cd webbit
make jar
В этот момент у вас должны быть каталоги build и lib в вашем каталоге webbit. Вам нужно скопировать webbit / build / webbit.jar и webbit / lib / netty-3.2.3.Final.jar в новый каталог, в котором вы собираетесь создать приложение Web Socket. Вы также можете создать пустой server.clj и index.html. Теперь у вас должен быть каталог, который выглядит примерно так:
-rw-r--r-- 1 jfields jfields 674 Feb 7 08:58 index.html
-rw-r--r-- 1 jfields jfields 786229 Feb 6 10:49 netty-3.2.3.Final.jar
-rw-r--r-- 1 jfields jfields 693 Feb 7 08:58 server.clj
-rw-r--r-- 1 jfields jfields 59616 Feb 6 10:49 webbit.jar
Далее мы запустим веббит с помощью Clojure. README WebBit дает нам пример Java, который легко конвертируется. Следующий код запускает сервер и печатает его аргументы при открытии, закрытии или отправке веб-сокета.
(ns server
(:require [clojure.contrib.json :as json]
[clojure.string :as s])
(:import [webbit WebServer WebServers WebSocketHandler]
[webbit.handler StaticFileHandler]))
(doto (WebServers/createWebServer 8080)
(.add "/websocket"
(proxy [WebSocketHandler] []
(onOpen [c] (println "opened" c))
(onClose [c] (println "closed" c))
(onMessage [c j] (println c j))))
(.add (StaticFileHandler. "."))
(.start))
(println "server up")
Вот и все. Сервер мало что делает, но работает. Запустите его, если хотите.
java -cp clojure.jar:webbit.jar:netty-3.2.3.Final.jar:clojure-contrib-1.2.0.jar clojure.main server.clj
(примечание: я использую Clojure 1.2)
Если все прошло хорошо, вы должны увидеть «server up», напечатанный на консоли. Мы пока оставим сервер работающим и соберем простой клиент.
Опять же, примеры уже в Интернете дают нам 90% того, что нам нужно. Мы собираемся использовать jquery-websocket , и пример внизу страницы как раз о том, что нам нужно. Следующий код является слегка измененной версией, которая должна соответствовать нашим целям.
<html>
<body>
<h1>WebSocket Demo</h1>
<input id="message" type="text"/>
<section id="content"></section>
<script src="http://www.google.com/jsapi"></script>
<script>google.load("jquery", "1.3")</script>
<script src="http://jquery-json.googlecode.com/files/jquery.json-2.2.min.js">
</script>
<script src="http://jquery-websocket.googlecode.com/files/jquery.websocket-0.0.1.js">
</script>
<script>
var ws = $.websocket("ws://127.0.0.1:8080/websocket", {
events: {
upcased: function(e) { $("#content").html(e.message); }}});
$('#message').change(function(){
ws.send('message', {type: "downcase", message: $("#message").val()});});
</script>
</body>
</html>
Наш клиент не очень большой, но он подключается к веб-сокету и отправляет сообщение в веб-сокет при изменении текста на входе.
Предполагая, что сервер все еще работает, вы сможете загрузить свою страницу.
Ваша страница не загружается? = (
Какой URL вы использовали? Мне сказали, что http: // localhost: 8080 / не работает так же хорошо, как http://127.0.0.1:8080/
Какой браузер вы использовали? У меня все работает в Chrome (версия 8.0.552.237)
Если ваша страница загружается, ваш сервер должен быть запущен. Вы должны увидеть нечто похожее на следующую строку в консоли вашего сервера.
opened #<NettyWebSocketConnection webbit.netty.NettyWebSocketConnection@8c5488>
Вы также можете напечатать что-нибудь на входе и выйти (или что вы предпочитаете делать, чтобы запустить событие «изменение»). Я набрал «привет» и получил следующую информацию в консоли сервера.
#<NettyWebSocketConnection webbit.netty.NettyWebSocketConnection@8c5488> {"type":"message","data":{"type":"downcase","message":"hello"}}
Ладно все работает Давайте добавим немного поведения на наш сервер. После получения сообщения наш сервер собирается взять текст, поставить его в регистр и отправить обратно клиенту.
Вот обновленная версия server.clj.
(ns server
(:require [clojure.contrib.json :as json]
[clojure.string :as s])
(:import [webbit WebServer WebServers WebSocketHandler]
[webbit.handler StaticFileHandler]))
(defn on-message [connection json-message]
(let [message (-> json-message json/read-json (get-in [:data :message]))]
(.send connection (json/json-str {:type "upcased" :message (s/upper-case message) }))))
(doto (WebServers/createWebServer 8080)
(.add "/websocket"
(proxy [WebSocketHandler] []
(onOpen [c] (println "opened" c))
(onClose [c] (println "closed" c))
(onMessage [c j] (on-message c j))))
(.add (StaticFileHandler. "."))
(.start))
(println "server up")
Новая версия server.clj использует преимущества поддержки json clojure.contrib. Конечным результатом этого является то, что мы можем работать с картами Clojure и в основном игнорировать json в нашем приложении.
После внесения вышеуказанных изменений в server.clj мы можем перезапустить наш сервер, обновить нашу веб-страницу, ввести текст, вставить вкладку из ввода, а затем мы должны увидеть наш текст на веб-странице в верхнем регистре.
И мы закончили. У нас работает клиент-серверное взаимодействие. Мы готовы запустить это в производство. Это так просто.
Возможно, вы заметили несколько вещей, которые делают магию случиться. На сервер мы отправили карту, которая имеет: тип «upcased». Этот тип соответствует событиям, которые определены в нашем клиенте. Jquery-websocket заботится о том, чтобы направить наше новое сообщение в функцию, связанную с upcased. Продолжая эту идею, вы можете отправлять сообщения с сервера разных типов и обрабатывать каждое из них в пользовательском интерфейсе как отдельное событие.
Вот и все. Приложение должно работать, и у вас должно быть все необходимое, чтобы начать расширять возможности приложения. Если у вас возникнут какие-либо проблемы, документация для webbit и jquery-websocket должна помочь вам.