Най-голямата спънка при разработката на богати уеб приложения до сега е липсата на двупосочна връзка – от клиента към сървъра и от сървъра към клиента. Решението на този проблем винаги е било голяма болка и страдания, като най-общо се ползват чести запитвания към сървъра, на които той в 90% от времето връща празен response или Comet (познато още като long polling най-общо). И двата начина са тромави и ресурсоемки… даже бих ги определил като законни DoS атаки. И всичко това за да се симулира нещо подобно на двупосочна връзка.
Е, дните на безсмислени request-и и празни response-и отминаха, защото HTML5 предлага няколко варианта за решение на този казус. Ще се спра само на един от тях, на тъй наречените Web Socket-и. Както сигурно се досещате става въпрос за сокет съединения, макар и леко модифицирани и орязани, които могат да се създават и управляват чрез Javascirpt. Освен че тези web socket-и могат само да започват връзка, но не и да стоят и да слушат за постъпване на такава, те имат и собствен допълнителен протокол, с който си комуникират със сървърното приложение. Важното в случая е че дуплексна връзка има и то на много ниска цена (от към писане на код). При създаване на сокет се оказват callback функции за четене, възникване на грешка и отваряне/затваряне на връзката, така че когато някое от изборените събития се случи, тези callback функции се извикват и обработката на данни пада във вашите ръце. Това намалява драстично главоболията породени от блокиращи/неблокиращи сокети, безкрайни цикли, exception-и и какво ли още не.
От сървърна гледна точка нещата също са прости, кодът който е нужен за успешна комуникация с клиента е съвсем стандартен за сървърно сокет приложение, с изключение на едни служебни съобщения, които Web Socket-ите очакват и от които не може да се бяга.
Понеже всичко до сега звучи прекалено хубаво, ще се наложи да ви приземя малко, защото Web Socket-и за сега се поддържат само от Google Chrome, но рано или късно и другите browser vendor-и ще се усетят откъде духа вятъра. И понеже вече се приземихте ето и едно примерно приложение, което сглобих – MultiDraw. Идеята е чрез HTML5 Canvas елемента и Web Socket-и да се постигне паралелно рисуване от множество клиенти върху платно. Сървърната част е на Python 2.6 и ползва модула asyncore от стандартната библиотека, който симулира асинхронно четене и писане от сокети.
Ето кодът, който се отнася до web socket-ите при клиента:
var s = new WebSocket("ws://" + document.location.host + ":6789/");
// създаване на сокет съединение на порт 6789
s.onopen = function(e) { document.title = 'MultiDraw - Online'; }
// функция, която да се изпълни при установена връзка
s.onclose = function(e) { document.title = 'MultiDraw - Offline'; }
// функция, която да се изпълни при прекратяване на връзка
s.onmessage = function(e) {
// функция, която да се изпълни при пристигане на съобщение (съобщението е в e.data)
var data = e.data.split(" "); // обработваме съобщението...
draw(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); // ... и чертаем върху Canvas-а
}
...
s.send([x, y, e.pageX, e.pageY, color, brushSize, lineCap, lineJoin].join(' ')); // изпращане на съобщение
При сървъра, единственото по-екзотично е хендшейк съобщението и това, че всяко съобщение започва с нулев байт и завършва с 0xFF (може да го видите в кода на сървъра).
Кодът на клиента и сървъра е тук – http://gist.github.com/339983 .
Happy Web Socketing 😉
P.S. Незнам дали забелязахте, ама редакторът на спецификацията за Web Socket-ите е “Ian Hickson, Google, Inc.”, така че няма нищо странно, че тези чудесии се появяват именно в Chrome за първи път 😛
Tags: Chrome, html5, WebSockets