socket.io 快速入門教程——聊天應(yīng)用

2020-08-10 10:39 更新

本教程將創(chuàng)建一個基本的聊天應(yīng)用。 它幾乎不要求你事先了解 Node.JS 或 Socket.IO ,適合所有知識層次的用戶。

簡介


使用流行的 web 應(yīng)用技術(shù)棧 —— 比如 LAMP (PHP) —— 來編寫聊天應(yīng)用通常是很困難的。它包含了輪詢服務(wù)器以檢測變化,還要追蹤時間戳,并且這種實現(xiàn)是比較慢的。

大多數(shù)實時聊天系統(tǒng)通?;?socket 來構(gòu)建。 Socket 為客戶端和服務(wù)器提供了雙向通信機制。

這意味著服務(wù)器可以 推送 消息給客戶端。無論何時你發(fā)布一條消息,服務(wù)器都可以接收到消息并推送給其他連接到服務(wù)器的客戶端。

web 框架


首先要制作一個 HTML 頁面來提供表單和消息列表。我們使用了基于 Node.JS 的 web 框架 express 。 請確保安裝了 Node.JS。

首先創(chuàng)建一個 package.json 來描述我們的項目。 推薦新建一個空目錄 (這里使用 chat-example)。


{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "description": "my first socket.io app",
  "dependencies": {}
}
    

要保存 dependencies 信息, 可以用 npm install --save

npm install --save express@4.15.2

express 已經(jīng)安裝好了。我們現(xiàn)在新建一個 index.js 文件來創(chuàng)建應(yīng)用。


var app = require('express')();
var http = require('http').Server(app);

app.get('/', function(req, res){
  res.send('<h1>Hello world</h1>');
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});
    

這段代碼作用如下:

  1. Express 初始化 app 作為 HTTP 服務(wù)器的回調(diào)函數(shù) (見第 2 行)。
  2. 定義了一個路由 / 來處理首頁訪問。
  3. 使 http 服務(wù)器監(jiān)聽端口 3000。

運行 node index.js 就可以看到如下畫面:

socket.io 快速入門教程——聊天應(yīng)用

在瀏覽器中訪問 http://localhost:3000

socket.io 快速入門教程——聊天應(yīng)用2

HTML 服務(wù)器


目前在 index.js 中我們是通過 res.send 返回一個 HTML 字符串。 如果我們將整個應(yīng)用的 HTML 代碼都放到應(yīng)用代碼里,代碼結(jié)構(gòu)將變得很混亂。 替代的方法是新建一個 index.html 文件作為服務(wù)器響應(yīng)。

現(xiàn)在我們用 sendFile 來重構(gòu)之前的回調(diào):


app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
    

index.html 內(nèi)容如下:


<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>
    

現(xiàn)在重啟進程 (按 Control+C ,然后再次運行 node index) ,刷新頁面顯示如下:

socket.io 快速入門教程——聊天應(yīng)用3

集成 Socket.IO


Socket.IO 由兩部分組成:

  • 一個服務(wù)端用于集成 (或掛載) 到 Node.JS HTTP 服務(wù)器: socket.io
  • 一個加載到瀏覽器中的客戶端: socket.io-client

開發(fā)環(huán)境下, socket.io 會自動提供客戶端。正如我們所見,到目前為止,我們只需要安裝一個模塊:

npm install --save socket.io

這會安裝模塊并添加依賴到 package.json。在 index.js 文件中添加該模塊:


var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});
    

我們通過傳入 http (HTTP 服務(wù)器) 對象初始化了 socket.io 的一個實例。 然后監(jiān)聽 connection 事件來接收 sockets, 并將連接信息打印到控制臺。

在 index.html 的 </body> 標(biāo)簽中添加如下內(nèi)容:


<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io();
</script>
    

這樣就加載了 socket.io-client。 socket.io-client 暴露了一個 io 全局變量,然后連接服務(wù)器。

請注意我們在調(diào)用 io() 時沒有指定任何 URL,因為它默認(rèn)將嘗試連接到提供當(dāng)前頁面的主機。

重新加載服務(wù)器和網(wǎng)站,你將看到控制臺打印出 “a user connected”。
嘗試打開多個標(biāo)簽頁,可以看到多條信息:

socket.io 快速入門教程——聊天應(yīng)用4

每個 socket 還會觸發(fā)一個特殊的 disconnect 事件:


io.on('connection', function(socket){
  console.log('a user connected');
  socket.on('disconnect', function(){
    console.log('user disconnected');
  });
});
    

你可以多次刷新標(biāo)簽頁來查看效果:

socket.io 快速入門教程——聊天應(yīng)用5

觸發(fā)事件


Socket.IO 的核心理念就是允許發(fā)送、接收任意事件和任意數(shù)據(jù)。任意能被編碼為 JSON 的對象都可以用于傳輸。二進制數(shù)據(jù) 也是支持的。

這里的實現(xiàn)方案是,當(dāng)用戶輸入消息時,服務(wù)器接收一個 chat message 事件。index.html 文件中的 script 部分現(xiàn)在應(yīng)該內(nèi)容如下:


<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js" rel="external nofollow" ></script>
<script>
  $(function () {
    var socket = io();
    $('form').submit(function(){
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });
  });
</script>
      

index.js 中打印出 chat message 事件:


io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    console.log('message: ' + msg);
  });
});
    

結(jié)果應(yīng)該如以下視頻所示:1

廣播


接下來的目標(biāo)就是讓服務(wù)器將消息發(fā)送給其他用戶。

要將事件發(fā)送給每個用戶,Socket.IO 提供了 io.emit 方法:

io.emit('some event', { for: 'everyone' });

要將消息發(fā)給除特定 socket 外的其他用戶,可以用 broadcast 標(biāo)志:


io.on('connection', function(socket){
  socket.broadcast.emit('hi');
});
    

為了簡單起見,我們將消息發(fā)送給所有用戶,包括發(fā)送者。


io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});
    

在客戶端中,我們捕獲 chat message 事件,并將消息添加到頁面中?,F(xiàn)在客戶端代碼應(yīng)該如下:


<script>
  $(function () {
    var socket = io();
    $('form').submit(function(){
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });
    socket.on('chat message', function(msg){
      $('#messages').append($('<li>').text(msg));
    });
  });
</script>
    

就這樣,聊天應(yīng)用就完成了,大約只有 20 行代碼! 最終效果如下:2

課外練習(xí)


下面是一些可以做的優(yōu)化:

  • 當(dāng)用戶連接和斷開連接時廣播消息
  • 添加昵稱
  • 不要將消息發(fā)送給服務(wù)器后再返回給發(fā)送者,應(yīng)該在用戶按下回車后立即將消息顯示到消息列表。
  • 添加 “{用戶} 正在輸入” 功能
  • 顯示在線用戶
  • 添加私密消息
  • 分享你的改進!

獲取示例


可以從 GitHub 獲取

$ git clone https://github.com/socketio/chat-example.git


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號