介紹了原生websocket的使用,接着學習使用socket.io:
socket.io 是基于 WebSocket 的 C-S 實時通信庫,底層是 engine.io,這個庫實作了跨平台的雙向通信。
engine.io 使用了 WebSocket 和 XMLHttprequest(或JSONP) 封裝了一套自己的 Socket 協定(暫時叫 EIO Socket),在低版本浏覽器裡面使用長輪詢替代 WebSocket。一個完整的 EIO Socket 包括多個 XHR 和 WebSocket 連接配接.
常用api:
socket.emit
資料傳輸對象為目前socket對應的client,其他各個client socket互相不影響;
socket.broadcast.emit
資料傳輸對象為所有client,排除目前socket對應的client;
io.sockets.emit
資料傳輸對象為所有client,包括觸發目前事件的client;
使用:
1.安裝express,聊天室需要區域網路的呀,區域網路需要啟動http服務呀,是以安裝express;
2.安裝socket.io,cnpm i --save socket.io 裝好後它分為前端、後端兩部分,前端頁面引入:<script src="/socket.io/socket.io.js"></script>(在檔案中看不到,等連接配接服務的時候就會出現),會自動生成一個檔案夾名字就叫socket.io,以及檔案夾内生成socket.io.js檔案
3.建立mainjs檔案,開始撸:
直接貼出寫好的代碼了:
mainjs:
var express = require("express");
var app = express();
//因為socket.io依賴原生http服務,是以要引入原生http子產品,并且調用它的Server()方法将app傳入,這樣原生的http就擁有了express的方法
var http = require("http").Server(app);
var socket = require("socket.io")(http);//傳入http執行socket函數,這樣socket就跟http具有同一個端口了
http.listen(9999);
app.use(express.static("./html"));//設定靜态資源路徑
// 建立socket監聽服務:
socket.on("connection", function(ws){
ws.on("diyLogin", function(val){//定義一個完全自定義事件,用來擷取前端發來的登入的使用者名
var address = ws.handshake.address;
console.log(address);
var u = checkUser(val);
if(u.err){
ws.emit("exist", u);
}else{
socket.sockets.emit("allLogin", u);//執行前端事件,發送範圍為每一個線上的用戶端
}
});
ws.on("sendMsg", function(msgObj){
socket.sockets.emit("accept", msgObj);//把接收到的某個使用者消息發送到所有用戶端
})
})
var arr = [];
function checkUser(u){//檢測使用者名是否已存在
if(arr.length === 0){
arr.push(u);
return u;
};
for(var i = 0; i < arr.length; i++){
if(arr[i] === u){
return {
err: "使用者名已存在",
users: arr
}
}
}
arr.push(u);
return u;
}
html:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" target="_blank" rel="external nofollow" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
i{
font-style: normal;
}
.chatList{
height: 200px;
border: 1px dashed green;
overflow-y: auto;
}
.myself{
text-align: right;
color: red;
}
i.lin{
font-weight: bold;
color: #ffcc01;
font-size: 16px;
}
i.other{
color: green;
}
p.me{
text-align: right;
color: orange;
}
</style>
</head>
<body>
<div class="container">
<div class="loginBox">
<input type="text" class="form-control" id="username">
<button class="btn" id="sure">登入</button>
</div>
<div class="chatBox hidden">
<div class="chatList">
</div>
<textarea class="form-control" id="msg" cols="30" rows="5"></textarea>
<button class="btn" id="send">發送</button>
<div class="alert alert-success hidden" role="alert"></div>
</div>
</div>
</body>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
//連結socket
var ws = io.connect("ws://localhost:9999");
var user;
$("#sure").click(function(){
var name = $("#username").val();
if(!name){
alert("好歹起個名呀,eg:李易峰");
}else{
//通知背景有人登陸了,socket.io都是基于事件的,要做的操作都是觸發自定義事件的方式
ws.emit("diyLogin", name);//執行自定義事件傳入使用者名
user = name;//把目前使用者名稱儲存到全局變量
}
})
//擷取後端傳回的使用者是否存在的查詢結果
ws.on("exist", function(re){
if(re.err){
alert(re.err);
console.log("已經登陸的使用者:\n", re.users)
return;
}
})
//接收後端傳回的全局的登入者的名字的事件
ws.on("allLogin", function(name){
var _alert = name === "趙治林" ? "歡迎 男爵 <i class='lin'>"+name+"</i> 騎着火麒麟來到了本直播間!" : "<i class='other'>"+name+" </i>進入直播間";
$(".alert").html(_alert).removeClass("hidden").show();
$(".loginBox").hide();//登陸後隐藏登入盒子
$(".chatBox").removeClass("hidden");//顯示出聊天界面
setTimeout(function(){
$(".alert").fadeOut(function(){
$(this).addClass("hidden");
});
}, 1500)
})
//發送聊天消息
$("#send").click(function(){
var msg = $("#msg").val();
if(!msg){
alert("空消息也要錢哦!");
}else{
ws.emit("sendMsg", {msg, user});//執行事件把内容和發送者發送給背景,讓背景傳回給所有用戶端
$("#msg").val("");
}
})
//接收聊天消息
ws.on("accept", function(o){
var p = $(`<p>${o.user}: ${o.msg}</p>`)
if(o.user === user){
p.addClass("me");
}
$(".chatList").append(p).scrollTop($(".chatList")[0].scrollHeight);
})
</script>
</html>
個人了解:
socket.io實作了一對多的B-S雙向通信,是基于事件驅動的,相當于背景自定義一個事件,前端觸發,前端自定義一個事件,背景觸發,同時可以選擇socket.io提供的方法指定資料發送的範圍,比如發給哪一個用戶端;