本文目錄一覽:
- 1、什麼是Websocket
- 2、前台h5 Socket.Io.js做客戶端,伺服器用Tomcat,java後台怎麼實現通訊。也是用socketio嗎?上詳細代碼。
- 3、如何用nodejs net進行聊天
- 4、如何使用Socket.IO編寫聊天應用程序
什麼是Websocket
認識HTML5的WebSocket
在HTML5規範中,我最喜歡的Web技術就是正迅速變得流行的WebSocket API。WebSocket提供了一個受歡迎的技術,以替代我們過去幾年一直在用的Ajax技術。這個新的API提供了一個方法,從客戶端使用簡單的語法有效地推動消息到伺服器。讓我們看一看HTML5的WebSocket API:它可用於客戶端、伺服器端。而且有一個優秀的第三方API,名為Socket.IO。
一、什麼是WebSocket API?
WebSocket API是下一代客戶端-伺服器的非同步通信方法。該通信取代了單個的TCP套接字,使用ws或wss協議,可用於任意的客戶端和伺服器程序。WebSocket目前由W3C進行標準化。WebSocket已經受到Firefox 4、Chrome 4、Opera 10.70以及Safari 5等瀏覽器的支持。
WebSocket API最偉大之處在於伺服器和客戶端可以在給定的時間範圍內的任意時刻,相互推送信息。WebSocket並不限於以Ajax(或XHR)方式通信,因為Ajax技術需要客戶端發起請求,而WebSocket伺服器和客戶端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允許跨域通信。
Ajax技術很聰明的一點是沒有設計要使用的方式。WebSocket為指定目標創建,用於雙向推送消息。
二、WebSocket API的用法
只專註於客戶端的API,因為每個伺服器端語言有自己的API。下面的代碼片段是打開一個連接,為連接創建事件監聽器,斷開連接,消息時間,發送消息返回到伺服器,關閉連接。
[Copy to clipboard] [ – ]
CODE:
// 創建一個Socket實例
var socket = new WebSocket(‘ws://localhost:8080’);
// 打開Socket
socket.onopen = function(event) {
// 發送一個初始化消息
socket.send(‘I am the client and I\’m listening!’);
// 監聽消息
socket.onmessage = function(event) {
console.log(‘Client received a message’,event);
};
// 監聽Socket的關閉
socket.onclose = function(event) {
console.log(‘Client notified socket has closed’,event);
};
// 關閉Socket….
//socket.close()
};
讓我們來看看上面的初始化片段。參數為URL,ws表示WebSocket協議。onopen、onclose和onmessage方法把事件連接到Socket實例上。每個方法都提供了一個事件,以表示Socket的狀態。
onmessage事件提供了一個data屬性,它可以包含消息的Body部分。消息的Body部分必須是一個字元串,可以進行序列化/反序列化操作,以便傳遞更多的數據。
WebSocket的語法非常簡單,使用WebSockets是難以置信的容易……除非客戶端不支持WebSocket。IE瀏覽器目前不支持WebSocket通信。如果你的客戶端不支持WebSocket通信,下面有幾個後備方案供你使用:
Flash技術 —— Flash可以提供一個簡單的替換。 使用Flash最明顯的缺點是並非所有客戶端都安裝了Flash,而且某些客戶端,如iPhone/iPad,不支持Flash。
AJAX Long-Polling技術 —— 用AJAX的long-polling來模擬WebSocket在業界已經有一段時間了。它是一個可行的技術,但它不能優化發送的信息。也就是說,它是一個解決方案,但不是最佳的技術方案。
由於目前的IE等瀏覽器不支持WebSocket,要提供WebSocket的事件處理、返回傳輸、在伺服器端使用一個統一的API,那麼該怎麼辦呢?幸運的是,Guillermo Rauch創建了一個Socket.IO技術。
三、帶Socket.IO的WebSocket
Socket.IO是Guillermo Rauch創建的WebSocket API,Guillermo Rauch是LearnBoost公司的首席技術官以及LearnBoost實驗室的首席科學家。Socket.IO使用檢測功能來判斷是否建立WebSocket連接,或者是AJAX long-polling連接,或Flash等。可快速創建實時的應用程序。Socket.IO還提供了一個NodeJS API,它看起來非常像客戶端API。
建立客戶端Socket.IO
Socket.IO可以從GitHub下載,可以把socket.io.js文件包含到頁面中:
[Copy to clipboard] [ – ]
CODE:
script src=””/script
[/code
此時,Socket.IO在此頁面上是有效的,是時候創建Socket了:
[code]
// 創建Socket.IO實例,建立連接
var socket= new io.Socket(‘localhost’,{
port: 8080
});
socket.connect();
// 添加一個連接監聽器
socket.on(‘connect’,function() {
console.log(‘Client has connected to the server!’);
});
// 添加一個連接監聽器
socket.on(‘message’,function(data) {
console.log(‘Received a message from the server!’,data);
});
// 添加一個關閉連接的監聽器
socket.on(‘disconnect’,function() {
console.log(‘The client has disconnected!’);
});
// 通過Socket發送一條消息到伺服器
function sendMessageToServer(message) {
socket.send(message);
}
Socket.IO簡化了WebSocket API,統一了返回運輸的API。傳輸包括:
WebSocket
Flash Socket
AJAX long-polling
AJAX multipart streaming
IFrame
JSONP polling
你還可以設置任意的Socket.IO構造器的第二個選項,選項包括:
port – 待連接的埠
transports – 一個數組,包含不同的傳輸類型
transportOptions – 傳輸的參數使用的對象,帶附加屬性
Socket.IO還提供了由本地WebSocket API提供的普通連接、斷開連接、消息事件。Socket還提供了封裝每個事件類型的方法。
四、NodeJS和Socket.IO聯合開發
Socket.IO提供的伺服器端解決方案,允許統一的客戶端和伺服器端的API。使用Node,你可以創建一個典型的HTTP伺服器,然後把伺服器的實例傳遞到Socket.IO。從這裡,你創建連接、斷開連接、建立消息監聽器,跟在客戶端一樣。
一個簡單的伺服器端腳本看起來如下:
[Copy to clipboard] [ – ]
CODE:
// 需要HTTP 模塊來啟動伺服器和Socket.IO
var http= require(‘http’), io= require(‘socket.io’);
// 在8080埠啟動伺服器
var server= http.createServer(function(req, res){
// 發送HTML的headers和message
res.writeHead(200,{ ‘Content-Type’: ‘text/html’ });
res.end(‘h1Hello Socket Lover!/h1’);
});
server.listen(8080);
// 創建一個Socket.IO實例,把它傳遞給伺服器
var socket= io.listen(server);
// 添加一個連接監聽器
socket.on(‘connection’, function(client){
// 成功!現在開始監聽接收到的消息
client.on(‘message’,function(event){
console.log(‘Received message from client!’,event);
});
client.on(‘disconnect’,function(){
clearInterval(interval);
console.log(‘Server has disconnected’);
});
});
你可以運行伺服器部分,假定已安裝了NodeJS,從命令行執行:
[Copy to clipboard] [ – ]
CODE:
node socket-server.js
現在客戶端和伺服器都能來回推送消息了!在NodeJS腳本內,可以使用簡單的JavaScript創建一個定期消息發送器:
[Copy to clipboard] [ – ]
CODE:
// 創建一個定期(每5秒)發送消息到客戶端的發送器
var interval= setInterval(function() {
client.send(‘This is a message from the server! ‘ + new Date().getTime());
},5000);
伺服器端將會每5秒推送消息到客戶端!
五、dojox.Socket和Socket.IO
Persevere的創建者Kris Zyp創建了dojox.Socket。dojox.Socket以Dojo庫一致的方式封裝了WebSocket API,用於在客戶端不支持WebSocket時,使用long-polling替代。
下面是怎樣在客戶端使用dojox.Socket和在伺服器端使用Socket.IO的例子:
[Copy to clipboard] [ – ]
CODE:
var args, ws= typeof WebSocket!= ‘undefined’;
var socket= dojox.socket(args= {
url: ws? ‘/socket.io/websocket’ : ‘/socket.io/xhr-polling’,
headers:{
‘Content-Type’:’application/x-www-urlencoded’
},
transport: function(args, message){
args.content = message; // use URL-encoding to send the message instead of a raw body
dojo.xhrPost(args);
};
});
var sessionId;
socket.on(‘message’, function(){
if (!sessionId){
sessionId= message;
args.url += ‘/’ + sessionId;
}else if(message.substr(0, 3) == ‘~h~’){
// a heartbeat
}
});
dojox.socket.Reconnect還創建了在套接字失去連接時自動重連。期待包含dojox.Socket的Dojo 1.6版本早日發布。
六、實際應用和WebSocket資源
有很多WebSocke的實際應用。WebSocket對於大多數客戶機-伺服器的非同步通信是理想的,在瀏覽器內聊天是最突出的應用。WebSocket由於其高效率,被大多數公司所使用。
WebSocket資源
Socket.IO站點:
WebSocket的Wikipedia:
WebSockets.org站點:
Dojo WebSocket站點:
前台h5 Socket.Io.js做客戶端,伺服器用Tomcat,java後台怎麼實現通訊。也是用socketio嗎?上詳細代碼。
socket.io封裝了websocket,同時包含了其它的連接方式,比如Ajax。原因在於不是所有的瀏覽器都支持websocket,通過socket.io的封裝,你不用關心裏面用了什麼連接方式。
你在任何瀏覽器里都可以使用socket.io來建立非同步的連接。socket.io包含了服務端和客戶端的庫,如果在瀏覽器中使用了socket.io的js,服務端也必須同樣適用。如果你很清楚你需要的就是websocket,那可以直接使用websocket
如何用nodejs net進行聊天
初始工作
安裝express, 用這個來託管socket.io,以及靜態頁面,命令npm install express –save,–save可以使包添加到package.json文件里.
安裝socket.io,命令npm install socket.io –save.
編寫服務端代碼
首先我們通過express來託管網站,並附加到socket.io實例里,因為socket.io初次連接需要http協議
var express = require(‘express’),
io = require(‘socket.io’);var app = express();app.use(express.static(__dirname));var server = app.listen(8888);var ws = io.listen(server);
添加伺服器連接事件,當客戶端連接成功之後,發公告告訴所有在線用戶,並且,當用戶發送消息時,發廣播通知其它用戶.
ws.on(‘connection’, function(client){
console.log(‘\033[96msomeone is connect\033[39m \n’);
client.on(‘join’, function(msg){
// 檢查是否有重複
if(checkNickname(msg)){
client.emit(‘nickname’, ‘昵稱有重複!’);
}else{
client.nickname = msg;
ws.sockets.emit(‘announcement’, ‘系統’, msg + ‘ 加入了聊天室!’);
}
});
// 監聽發送消息
client.on(‘send.message’, function(msg){
client.broadcast.emit(‘send.message’,client.nickname, msg);
});
// 斷開連接時,通知其它用戶
client.on(‘disconnect’, function(){
if(client.nickname){
client.broadcast.emit(‘send.message’,’系統’, client.nickname + ‘離開聊天室!’);
}
})})
由於客戶端是通過昵稱來標識的,所以服務端需要一個檢測昵稱重複的函數
// 檢查昵稱是否重複var checkNickname = function(name){
for(var k in ws.sockets.sockets){
if(ws.sockets.sockets.hasOwnProperty(k)){
if(ws.sockets.sockets[k] ws.sockets.sockets[k].nickname == name){
return true;
}
}
}
return false;}
編寫客服端代碼
由於服務端採用第三方websokcet框架,所以前端頁面需要單獨引用socket.io客戶端代碼,源文件可以從socket.io模塊里找,windows下路徑為node_modules\socket.io\node_modules\socket.io-client\dist,這裡有開發版和壓縮版的,默認引用開發版就行.
前端主要處理輸入昵稱檢查,消息處理,完整代碼如下
!DOCTYPE htmlhtmlhead
titlesocket.io 聊天室例子/title
meta charset=”utf-8″
link rel=”stylesheet” href=”css/reset.css”/
link rel=”stylesheet” href=”css/bootstrap.css”/
link rel=”stylesheet” href=”css/app.css”//headbody
div class=”wrapper”
div class=”content” id=”chat”
ul id=”chat_conatiner”
/ul
/div
div class=”action”
textarea /textarea
button class=”btn btn-success” id=”clear”清屏/button
button class=”btn btn-success” id=”send”發送/button
/div
/div
script type=”text/javascript” src=”js/socket.io.js”/script
script type=”text/javascript”
var ws = io.connect(”);
var sendMsg = function(msg){
ws.emit(‘send.message’, msg);
}
var addMessage = function(from, msg){
var li = document.createElement(‘li’);
li.innerHTML = ‘span’ + from + ‘/span’ + ‘ : ‘ + msg;
document.querySelector(‘#chat_conatiner’).appendChild(li);
// 設置內容區的滾動條到底部
document.querySelector(‘#chat’).scrollTop = document.querySelector(‘#chat’).scrollHeight;
// 並設置焦點
document.querySelector(‘textarea’).focus();
}
var send = function(){
var ele_msg = document.querySelector(‘textarea’);
var msg = ele_msg.value.replace(‘\r\n’, ”).trim();
console.log(msg);
if(!msg) return;
sendMsg(msg);
// 添加消息到自己的內容區
addMessage(‘你’, msg);
ele_msg.value = ”;
}
ws.on(‘connect’, function(){
var nickname = window.prompt(‘輸入你的昵稱!’);
while(!nickname){
nickname = window.prompt(‘昵稱不能為空,請重新輸入!’)
}
ws.emit(‘join’, nickname);
});
// 昵稱有重複
ws.on(‘nickname’, function(){
var nickname = window.prompt(‘昵稱有重複,請重新輸入!’);
while(!nickname){
nickname = window.prompt(‘昵稱不能為空,請重新輸入!’)
}
ws.emit(‘join’, nickname);
});
ws.on(‘send.message’, function(from, msg){
addMessage(from, msg);
});
ws.on(‘announcement’, function(from, msg){
addMessage(from, msg);
});
document.querySelector(‘textarea’).addEventListener(‘keypress’, function(event){
if(event.which == 13){
send();
}
});
document.querySelector(‘textarea’).addEventListener(‘keydown’, function(event){
if(event.which == 13){
send();
}
});
document.querySelector(‘#send’).addEventListener(‘click’, function(){
send();
});
document.querySelector(‘#clear’).addEventListener(‘click’, function(){
document.querySelector(‘#chat_conatiner’).innerHTML = ”;
});
/script/body/html
如何使用Socket.IO編寫聊天應用程序
我們將首先通過查看客戶端代碼。所有聊天互動都有HomeView處理,首先需要在 /public/js/models/main.js中定義HomeModel。
var HomeModel = Backbone.Model.extend({
defaults: {
// Backbone collection for users
onlineUsers: new UserCollection(),
// Backbone collection for user chats, 初始化一個預定義聊天模型
userChats: new ChatCollection([
new ChatModel({sender: ”, message: ‘Chat Server v.1’})
])
},
// 添加一個新用戶到 onlineUsers collection
addUser: function(username) {
this.get(‘onlineUsers’).add(new UserModel({name: username}));
},
// 從onlineUsers collection中移除一個用戶
removeUser: function(username) {
var onlineUsers = this.get(‘onlineUsers’);
var u = onlineUsers.find(function(item) {
return item.get(‘name’) == username;
});
if (u) {
onlineUsers.remove(u);
}
},
// 添加一個新的聊天到 userChats collection
addChat: function(chat) {
this.get(‘userChats’).add(new ChatModel({sender: chat.sender, message: chat.message}));
},
});
我們利用Backbone集合來偵聽集合變化。這些集合的更新會直接由視圖自動反映出來。接下來,需要在/public/index.html中定義home模板。
script type=”text/template” id=”home-template”
div class=”row”
div class=”col-md-10″
div class=”panel panel-default”
div class=”panel-heading”Lobby/div
div class=”panel-body”
div class=”nano”
div class=”content”
div class=”list-group” id=”chatList”/div
/div
/div
form
input class=”form-control” type=”text” id=”chatInput”/input
/form
/div
/div
/div
div class=”col-md-2″
div class=”panel panel-default”
div class=”panel-heading”
h3 class=”panel-title”Online Users span class=”badge pull-right” id=”userCount”/span/h3
/div
div class=”panel-body”
div class=”nano”
div class=”content”
div class=”list-group” id=”userList”/div
/div
/div
/div
/div
/div
/div
/script
聊天客戶端
接下來, 讓我們來定義 我們的 Socket.IO 聊天客戶端 。 客戶端 與伺服器端的通信,主要通過發送消息和監聽通知 來完成。 這些通知 觸發事件 與所述控制器 進行通信。請參閱 下面 /public/ JS / socketclient.js的代碼 。
var ChatClient = function(options) {
// 避免衝突
var self = this;
// app event bus
self.vent = options.vent;
// server hostname replace with your server’s hostname eg:
self.hostname = ”;
// connects to the server
self.connect = function() {
// connect to the host
self.socket = io.connect(self.hostname);
// set responseListeners on the socket
self.setResponseListeners(self.socket);
}
// send login message
self.login = function(name) {
self.socket.emit(‘login’, name);
}
// send chat message
self.chat = function(chat) {
self.socket.emit(‘chat’, chat);
}
self.setResponseListeners = function(socket) {
// handle messages from the server
socket.on(‘welcome’, function(data) {
// request server info
socket.emit(‘onlineUsers’);
self.vent.trigger(‘loginDone’, data);
});
socket.on(‘loginNameExists’, function(data) {
self.vent.trigger(‘loginNameExists’, data);
});
socket.on(‘loginNameBad’, function(data) {
self.vent.trigger(‘loginNameBad’, data);
});
socket.on(‘onlineUsers’, function(data) {
console.log(data);
self.vent.trigger(‘usersInfo’, data);
});
socket.on(‘userJoined’, function(data) {
self.vent.trigger(‘userJoined’, data);
});
socket.on(‘userLeft’, function(data) {
self.vent.trigger(‘userLeft’, data);
});
socket.on(‘chat’, function(data) {
self.vent.trigger(‘chatReceived’, data);
});
}
}
使用Socket.IO可以非常簡單的發送和接受通信數據,上面的代碼中,使用了下面的兩個方法
socket.emit(message, [callback]) 向伺服器端發送消息
socket.on(message, callback) 用於接收來自伺服器的消息
讓我們來看一下他們的通信協議
主控制器
客戶端最後一步,主控制器,它控制了VIEW,MODEL和socket客戶端,代碼在/public/js/main.js中
var MainController = function() {
var self = this;
// Event Bus for socket client
self.appEventBus = _.extend({}, Backbone.Events);
// Event Bus for Backbone Views
self.viewEventBus = _.extend({}, Backbone.Events);
// initialize function
self.init = function() {
// create a chat client and connect
self.chatClient = new ChatClient({vent: self.appEventBus});
self.chatClient.connect();
// create our views, place login view inside container first.
self.loginModel = new LoginModel();
self.containerModel = new ContainerModel({
viewState: new LoginView({
vent: self.viewEventBus,
model: self.loginModel
})
});
self.containerView = new ContainerView({model: self.containerModel});
self.containerView.render();
};
// View Event Bus Message Handlers
self.viewEventBus.on(‘login’, function(name) {
// socketio login
self.chatClient.login(name);
});
self.viewEventBus.on(‘chat’, function(chat) {
// socketio chat
self.chatClient.chat(chat);
});
// Socket Client Event Bus Message Handlers
// triggered when login success
self.appEventBus.on(‘loginDone’, function() {
self.homeModel = new HomeModel();
self.homeView = new HomeView({vent: self.viewEventBus, model: self.homeModel});
// set viewstate to homeview
self.containerModel.set(‘viewState’, self.homeView);
});
// triggered when login error due to bad name
self.appEventBus.on(‘loginNameBad’, function(name) {
self.loginModel.set(‘error’, ‘Invalid Name’);
});
// triggered when login error due to already existing name
self.appEventBus.on(‘loginNameExists’, function(name) {
self.loginModel.set(‘error’, ‘Name already exists’);
});
// triggered when client requests users info
// responds with an array of online users.
self.appEventBus.on(‘usersInfo’, function(data) {
var onlineUsers = self.homeModel.get(‘onlineUsers’);
var users = _.map(data, function(item) {
return new UserModel({name: item});
});
onlineUsers.reset(users);
});
// triggered when a client joins the server
self.appEventBus.on(‘userJoined’, function(username) {
self.homeModel.addUser(username);
self.homeModel.addChat({sender: ”, message: username + ‘ joined room.’});
});
// triggered when a client leaves the server
self.appEventBus.on(‘userLeft’, function(username) {
self.homeModel.removeUser(username);
self.homeModel.addChat({sender: ”, message: username + ‘ left room.’});
});
// triggered when chat receieved
self.appEventBus.on(‘chatReceived’, function(chat) {
self.homeModel.addChat(chat);
});
}
最後,我們需要定義一個MainController入口,調用init方法,代碼位於/public/js/main.js中
聊天伺服器端
應用程序的最後一部分是聊天伺服器。它主要負責維護在線用戶列表,廣播聊天消息。比如,首先,伺服器會給一個新的客戶的連接請求命名,然後通過剛剛建立的socket,連接事件handlers。socket handler處理如下事件: socket.on(message, callback) – 在收到新郵件時回調函數被調用。消息可以是任何類型的數據,這取決於發送的消息。 socket.on(‘disconnect’, callback) – 當socket斷開連接時候,回調函數被調用。 socket.emit(message, args) – 通過socket發送消息。 socket.broadcast.send(message, args) – 廣播信息到除發送者之外的所有socket。現在,我們已經看到了handler socket是如何工作的。首先,需要在/scripts/chatserver.js中定義一個用戶模型 :
總結
我們已經看到了如何使用Backbone和Socket.IO構建一個簡單的聊天應用程序。還有很多沒有在本文中涉及的Socket.IO性能,例如rooms和namespaces。通過這篇文章,我們可以看出使用Socket.IO很容易的在客戶端和伺服器端交換消息。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/294088.html