Sunteți pe pagina 1din 13

Ministerul Educației al Republicii Moldova

Universitatea Tehnică a Moldovei


Facultatea Calculatoare, Informatică și Microelectronică
Catedra Automatica și Tehnologii Informaționale

RAPORT
Disciplina: Programarea în rețea

Tema: Web Sockets

A efectuat: st. grupei SI-131


Gheorghisenco L.

A verificat: Antohi Ion

Chişinǎu 2016
Cuprins

Introducere..................................................................................................................................................................................3
 Scopul lucrării..............................................................................................................................................................3
 Obiectivele lucrării....................................................................................................................................................3
Indicații teoretice......................................................................................................................................................................3
Realizarea lucrării.....................................................................................................................................................................4
Utilizarea...................................................................................................................................................................................11
Concluzie..................................................................................................................................................................................12
Bibliografie..............................................................................................................................................................................12

2
Scopul lucrării:
Studiul noilor abordări pentru comunicarea în spațiul Web.

Obiectivele lucrării:
Elaborarea unei aplicații client-server simple ce ar utiliza protocolul Websockets pentru
comunicare.

Indicații teoretice.
WebSocket este un protocol care asigura canale de comunitie full-duplex printr-o singură
conexiune TCP. WebSocket este conceput pentru a fi aplicat în web browsere și web servere, dar poate fi
utilizat de către orice aplicatie client-server. Protocolul WebSocket este un protocol bazat pe TCP. Relatia
cu HTTP este ca handshake este interpretat de servere HTTP ca o cerere de upgrade. Protocolul
WebSocket face posibilă o interacțiunea mai bune dintre browser și un site web, facilitând conținut live și
crearea de jocuri în timp real. Acest lucru este posibil prin furnizarea de un mod standardizat pentru
server pentru a trimite conținut în browser, fără a fi solicitate de către client, și pentru a permite mesajelor
să fie trecut înainte și înapoi păstrând în același timp conexiunea deschisă. În acest fel, conversația(bi-
directional) poate avea loc între browser și server. În plus, comunicările se fac prin TCP, portul 80, care
este un beneficiu pentru aceste medii care blocheaza conexiunile la Internet non-web folosind un firewall.
Spre deosebire de HTTP, WebSocket prevede comunicare full-duplex. În plus, Websocket permite
fluxuri de mesaje pe partea de sus a TCP. TCP se ocupă doar cu fluxuri de bytes. Pentru a stabili o
conexiune WebSocket, clientul trimite o cerere de WebSocket handshake, care serverul returnează un
răspuns WebSocket handshake, așa cum se arată în următorul exemplu:
Cererea clientului:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

Raspunsul serverului:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

3
Odată ce conexiunea este stabilită, clientul și serverul poat trimite date WebSocket sau frames de
text și înapoi în modul full-duplex. Datele sunt minimal incapsulate, cu un header mic. Transmisii
WebSocket sunt descrise ca "mesaje", care un singur mesaj poate fi opțional împărțită în mai multe
frame-uri de date. Acest lucru poate permite trimiterea de mesaje în care date inițială este disponibilă, dar
lungimea completă a mesajului este necunoscut (se trimite un frame de date după altul până când se
ajunge la sfârșitul și a marcat cu bitul FIN). Cu extensii ale protocolului, acest lucru poate fi de asemenea
utilizat pentru mai multe fluxuri de multiplexare simultan (de exemplu, pentru a evita utilizarea
monopolizarea unei prize pentru o singură sarcină utilă mare).
Este important (dintr-o perspectivă de securitate) este mai bine să folosiți token-uri sau
mecanisme de protecție similare pentru a autentifica conexiunea WebSocket când datele (privat) sunt
transferate pe WebSocket.

Realizarea lucrării.

Aplicația constă din două părți principale care reprezintă Back-end-ul și respectiv Front-end-ul cu
numele respective: chat-server.js și frontend.js.
În fișierul chat-server.js se realizează un server de tip webSocketServer, se initializează datele
necesare pentru a stoca utilizatorii într-un vector precum și a întregii istorii pentru ca utilizatorii noi să
poată vedea toate mesajele discutate anterior. In mare parte el se ocupa de gestiune a clientilor,
pastrarea conexiunii pentru a duce contul de toti clienti.
Următoarea secvență de cod inițializează web serverul de tip webSocketServer și implementează
funcțiile pentru evenimentele de bază unde înregistrează utilizatorii, prelucrează mesajele acestora și le
transmite mai departe:

/ Port where we'll run the websocket


server var webSocketsServerPort = 1337;

/ websocket and http servers


var webSocketServer = require('websocket').server;
var http = require('http');

/**
* Global
variables */
// entire message history
4
var history = new Array();
/ list of currently connected clients (users)
var clients = new Array();

/ Array with some colors


var colors = [ 'red', 'green', 'blue', 'magenta', 'purple', 'plum', 'orange' ];
// ... in random order
colors.sort(function(a,b) { return Math.random() > 0.5; } );

/**
* HTTP
server */
var server = http.createServer(function(request, response) {
// Not important for us. We're writing WebSocket server, not HTTP server
});
server.listen(webSocketsServerPort, function() {
console.log((new Date()) + " Server is listening on port " +
webSocketsServerPort); });

/**
* WebSocket
server */
var wsServer = new webSocketServer({
// WebSocket server is tied to a HTTP server. To be honest I don't understand why.
httpServer: server
});

/ This callback function is called every time someone tries to connect to the WebSocket server
/ here we need to introduce certificate to use secure connection
wsServer.on('request', function(request) {
console.log((new Date()) + ' Connection from origin ' + request.origin + '.');

// accept connection
var connection = request.accept(null, request.origin);
// we need to know client index to remove them on 'close' event
5
var index = clients.push(connection) -
1; var userName = false;
var userColor = false;

console.log((new Date()) + ' Connection accepted.');

/ send back chat history


if (history.length > 0) {
connection.sendUTF(JSON.stringify( { type: 'history', data: history} ));
}

/ user sent some message


connection.on('message', function(message) {
if (message.type === 'utf8') { // accept only text
if (userName === false) { // first message sent by user is their name
/ remember user name
userName = message.utf8Data;
/ get random color and send it back to the user
userColor = colors.shift();
connection.sendUTF(JSON.stringify({ type:'color', data: userColor }));
console.log((new Date()) + ' User is known as: ' + userName
+ ' with ' + userColor + '

color.'); } else { // log and broadcast the

message

console.log((new Date()) + ' Received Message from '


+ userName + ': ' + message.utf8Data);

/ we want to keep history of all sent


messages var obj = {
time: (new Date()).getTime(),
text: message.utf8Data,
author: userName,
color: userColor
};
history.push(obj);
6
// broadcast message to all connected clients
var json = JSON.stringify({ type:'message', data: obj });
for (var i=0; i < clients.length; i++) {
clients[i].sendUTF(json);
}
}
}
});

// user disconnected
connection.on('close', function(connection) {
if (userName !== false && userColor !== false) {
console.log((new Date()) + " Peer " + connection.remoteAddress + " disconnected.");
/ remove user from the list of connected clients
clients.splice(index, 1);
/ push back user's color to be reused by another
user colors.push(userColor);
}
});

});

În acest fragment de cod este arătat cum se crează un socket și se conectează la un port și așteaptă să se
conecteze clienții la el. Apoi fiecare conexiune este pastrată într-o lista pentru a duce contul fiecărui
client.

„frontend.js” reprezinta clientul si ideea principală al acestuia este de a se conecta la server, a deschide
stream-urile pentru comunicare și gestiune a mesajelor. Mai jos este prezentat fragmentul de cod care
raspunde de conectarea la server, crearea stream-urilor și ascultarea serverului pentru primirea mesajelor.

// frontend.js $
(function () {
"use strict";

7
/ for better performance - to avoid searching in
DOM var content = $('#content');
var input = $('#input');
var status = $('#status');

/ my color assigned by the server


var myColor = false;
/ my name sent to the
server var myName = false;

/ if user is running mozilla then use it's built-in WebSocket


window.WebSocket = window.WebSocket || window.MozWebSocket;

/ if browser doesn't support WebSocket, just show some notification and exit
if (!window.WebSocket) {
content.html($('<p>', { text: 'Sorry, but your browser doesn\'t '
+ 'support WebSockets.'} ));
input.hide(); $
('span').hide();
return;
}

// open connection
var connection = new WebSocket('ws://localhost:1337');

connection.onopen = function () {
// first we want users to enter their names
input.removeAttr('disabled').val('').focus();
status.text('Choose name:');
};

connection.onerror = function (error) {


// just in there were some problems with conenction...
content.html($('<p>', { text: 'Sorry, but there\'s some problem with your
' + 'connection or the server is down.</p>' } ));
8
};

// most important part - incoming messages


connection.onmessage = function (message) {
/ try to parse JSON message. Because we know that the server always returns
/ JSON this should work without any problem but we should make sure that
/ the massage is not chunked or otherwise damaged.
try {
var json = JSON.parse(message.data);
} catch (e) {
console.log('This doesn\'t look like a valid JSON: ', message.data);
return;
}

/ NOTE: if you're not sure about the JSON structure


/ check the server source code above
if (json.type === 'color') { // first response from the server with user's color
myColor = json.data;
status.text(myName + ': ').css('color',
myColor); input.removeAttr('disabled').focus();
/ from now user can start sending messages
} else if (json.type === 'history') { // entire message history
/ insert every single message to the chat window
for (var i=0; i < json.data.length; i++)
{ addMessage(json.data[i].author, json.data[i].text,
json.data[i].color, new Date(json.data[i].time));
}
slideScrollbar();
} else if (json.type === 'message') { // it's a single message
input.removeAttr('disabled'); // let the user write another message
addMessage(json.data.author, json.data.text,
json.data.color, new Date(json.data.time));
slideScrollbar();
} else {
console.log('Hmm..., I\'ve never seen JSON like this: ', json);
9
}
};

/**
* Send mesage when user presses Enter key
*/
input.keydown(function(e)
{ if (e.keyCode === 13) {
var msg = $(this).val();
/ send the message as an ordinary text
connection.send(msg);
$(this).val('');
/ disable the input field to make the user wait until server
/ sends back response
input.attr('disabled', 'disabled');

// we know that the first message sent from a user their


name if (myName === false) {
myName = msg;
}
}
});

/**
* This method is optional. If the server wasn't able to respond to the
* in 3 seconds then show some error message to notify the user that
* something is wrong.
*/
setInterval(function() {
if (connection.readyState !== 1)
{ status.text('Error');
input.attr('disabled', 'disabled').val('Unable to comminucate
' + 'with the WebSocket server.');
}
}, 5000);
10
/**
* Add message to the chat window
*/
function addMessage(author, message, color, datetime) {
content.append('<p><span style="color:' + color + '">' + author + '</span> @ ' +
+ (datetime.getHours() < 10 ? '0' + datetime.getHours() : datetime.getHours()) + ':'
+ (datetime.getMinutes() < 10 ? '0' + datetime.getMinutes() : datetime.getMinutes())
+ ': ' + message + '</p>');
}

Rezultatele obtinute:

Fig. 1 – Rezultatul rularii

Fig. 2 – Rezultatul rularii partii front-end.

11
Concluzie.
In concluzie pot spune ca WebSockets este o abordare noua in domeniul web. Web Sockets este
un pas enorm înainte în scalabilitatea web-ului în timp real. Reducerea în traficului HTTP inutile și
reducere latența. Aceasta nu este doar o imbunatatire, dar este un salt revolutionar innainte.
De ceva timp programatorii încercau să ofere soluții cît mai bune pentru realizarea aplicațiilor web
în timp real cum ar fi chat-urile, sau jocurile ș.a. Evident toate aceste tehnologii trebuiau să se bazeze pe
protocolul HTTP care nu permite o conexiune permanentă între client-server. Printre tehnologiile larg
răspîndite și de success pînă acum au fost Ajax-pooling, Ajax-long-pooling, commet care nu făceau nimic
altceva decît să ceară în background la un anumit interval de timp niște date de la server, sau în cazul
tehnologiei commet serverul să notifice clientul în cazul unor modificări.
În 2011 însă apare așa numitul WebSocket care este un protocol care asigura canale de comunitie
full-duplex printr-o singură conexiune TCP. WebSocket este conceput pentru a fi aplicat în web
browsere și web servere, dar poate fi utilizat de către orice aplicatie client-server. Protocolul WebSocket
este un protocol bazat pe TCP. Relatia cu HTTP este ca handshake este interpretat de servere HTTP ca o
cerere de upgrade. Protocolul WebSocket face posibilă o interacțiunea mai bune dintre browser și un site
web, facilitând conținut live și crearea de jocuri în timp real.
La început protocolul era compatibil doar cu cîteva browsere ceea ce făcea programatorii să
renunțe la folosirea acestuia, chiar dacă acesta aducea multe facilități. Cu trecerea timpului din fericire
protocolul a devenit astăzi suportat de majoritatea browserelor și avem access full-duplex între client-
server ceea ce oferă posibilitatea creării applicațiilor web în timp-real de o performanță incredibilă.
Mai mult de atît la apariția protocolului acesta era implementat doar în cîteva limbaje
primile dintre care fiind NodeJS în care și este realizată aplicația din laborator.

Bibliografia.
A. Tanenbaum, Reţele de calculatoare (ediţia a patra), Byblos, Tg.Mureş, 2003

12