Socket.io快速入門

1、基本概念

Socket.IO 是一個基於 Node.js 的實時應用程序框架,在即時通信、通知與消息推送,實時分析等場景中有較爲普遍的應用。javascript

WebSocket 的產生源於 Web 開發中日益增加的實時通訊需求,對比基於 http 的輪詢方式,它大大節省了網絡帶寬,同時也下降了服務器的性能消耗; socket.io 支持 websocket、polling 兩種數據傳輸方式以兼容瀏覽器不支持 WebSocket 場景下的通訊需求。css

WebSocket是HTML5最新提出的規範,雖然主流瀏覽器都已經支持,但仍然可能有不兼容的狀況,爲了兼容全部瀏覽器,給程序員提供一致的編程體驗,SocketIO將WebSocket、AJAX和其它的通訊方式所有封裝成了統一的通訊接口,也就是說,咱們在使用SocketIO時,不用擔憂兼容問題,底層會自動選用最佳的通訊方式。所以說,WebSocket是SocketIO的一個子集。html

2、應用

首先要製做一個 HTML 頁面來提供表單和消息列表。咱們使用了基於 Node.JS 的 web 框架 express 。 請確保安裝了 Node.JS前端

首先建立一個 package.json 來描述咱們的項目。 推薦新建一個空目錄 (這裏使用 chat-example)。java

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

安裝相關依賴:node

npm install --save express@4.15.2
npm install --save socket.io

前端頁面:
index.htmljquery

<!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>

  <script src="/socket.io/socket.io.js"></script>
  <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js" rel="external nofollow"></script>

<script>
  // 請注意咱們在調用 io() 時沒有指定任何 URL,由於它默認將嘗試鏈接到提供當前頁面的主機。
    /*
    var socket = io();


    $('form').submit(function(){
      alert($('#m').val());
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });
    */

 $(function () {
    var socket = io();
    $('form').submit(function(){
      alert($('#m').val());
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });

    socket.on('chat message', function(msg){
      $('#messages').append($('<li>').text(msg));
    });

    
  });
</script>
</html>

服務端頁面 index.js:程序員

// 一、Express 初始化 app 做爲 HTTP 服務器的回調函數
var app = require('express')();   
var http = require('http').Server(app)

var io = require('socket.io')(http);


// 二、定義了一個路由 / 來處理首頁訪問。
/*
app.get('/', function(req, res){
  res.send('<h1>Hello world</h1>');
});
*/
app.get('/', function(req, res) {
  res.sendFile(__dirname + '/index.html');
});


// 三、使 http 服務器監聽端口 3000
http.listen(3000, function(){
    console.log('listening on *:3000');
})

// ================== io 通訊 =====================
// 客戶端頁面打開時會和服務端創建鏈接
/*
io.on('connection', function(socket){
  console.log('a user connected');
});
*/


// 每一個 socket 還會觸發一個特殊的 disconnect 事件:
/*
io.on('connection', function(socket){
  console.log('a user connected');
  socket.on('disconnect', function(){
    console.log('user disconnected');
  });
});
*/

// 當用戶輸入消息時,服務器接收一個 chat message 事件
/*
io.on('connection', function(socket){
   console.log('a user connected');

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

// 廣播,講消息發送給全部用戶,包括髮送者
io.on('connection', function(socket){
  socket.on('chat message', function(msg){

      // 發送消息給客戶端(全部客戶端都會收到)
    io.emit('chat message', msg);
  });
});

啓動服務:web

dell@DESKTOP-KPEE6OO MINGW64 /C/work/other/socket-chat
$ node index.js
listening on *:3000

訪問界面:
image.pngexpress

3、升級版

先看界面:
image.png

服務端 index_plus.js

//建立一個http服務器
var app = require('http').createServer()

// 把http封裝成io對象
var io = require('socket.io')(app)

// 運行的服務器端口號
var PORT = 3000
var clientCount = 0

// 監聽端口
app.listen(PORT)

io.on('connection', function (socket) {
  // 給每一個用戶取名字
  clientCount++
  socket.nickname = 'user' + clientCount

  // io.emit表明廣播,socket.emit表明私發
  io.emit('enter', socket.nickname + '  comes in')

   // socket.on 表示服務器接收一個客戶端message 事件
  socket.on('message', function (str) {
    // io.emit表示從服務端給客戶端發送一個消息
    io.emit('message', socket.nickname + ' says: ' + str)
  })

  // 客戶端斷開,自帶事件
  socket.on('disconnect', function () {
    io.emit('leave', socket.nickname + ' left')
  })
})

客戶端:index_plus.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>聊天室</title>
  <!-- cdn -->
  <script src="https://cdn.bootcss.com/socket.io/2.3.0/socket.io.js"></script>
</head>

<body>
  <h1>聊天室</h1>
  <input id="sendTxt" type="text" />
  <button id="sendBtn">發送</button>
  <div id="recv"></div>
  <script type="text/javascript">

    var socket = io("ws://localhost:3000/");

    //把接收的數據顯示到界面
    function showMessage(str, type) {
      var div = document.createElement('div');
      div.innerHTML = str;
      if (type == "enter") {
        div.style.color = 'blue';
      } else if (type == "leave") {
        div.style.color = "red"
      }
      document.body.appendChild(div)
    }

    // 點擊以後發送
    document.getElementById("sendBtn").onclick = function () {
      var txt = document.getElementById("sendTxt").value;
      if (txt) {        // 文本不爲空發送
        socket.emit('message', txt);
      }
    }

    // 第一個enter表明是進入事件,第二個enter爲了顯示須要
    socket.on('enter', function (data) {
      showMessage(data, 'enter')
    })

    socket.on('message', function (data) {
      showMessage(data, 'message')
    })

    socket.on('leave', function (data) {
      showMessage(data, 'leave')
    })


  </script>
</body>
</html>

啓動:

dell@DESKTOP-KPEE6OO MINGW64 /C/work/other/socket-chat
$ node index_plus.js

4、事件速查表

io.on('connect', onConnect);

function onConnect(socket){

  // 發送給當前客戶端
  socket.emit('hello', 'can you hear me?', 1, 2, 'abc');

  // 發送給全部客戶端,除了發送者
  socket.broadcast.emit('broadcast', 'hello friends!');

  // 發送給同在 'game' 房間的全部客戶端,除了發送者
  socket.to('game').emit('nice game', "let's play a game");

  // 發送給同在 'game1' 或 'game2' 房間的全部客戶端,除了發送者
  socket.to('game1').to('game2').emit('nice game', "let's play a game (too)");

  // 發送給同在 'game' 房間的全部客戶端,包括髮送者
  io.in('game').emit('big-announcement', 'the game will start soon');

  // 發送給同在 'myNamespace' 命名空間下的全部客戶端,包括髮送者
  io.of('myNamespace').emit('bigger-announcement', 'the tournament will start soon');

  // 發送給指定 socketid 的客戶端(私密消息)
  socket.to(<socketid>).emit('hey', 'I just met you');

  // 包含回執的消息
  socket.emit('question', 'do you think so?', function (answer) {});

  // 不壓縮,直接發送
  socket.compress(false).emit('uncompressed', "that's rough");

  // 若是客戶端還不能接收消息,那麼消息可能丟失
  socket.volatile.emit('maybe', 'do you really need it?');

  // 發送給當前 node 實例下的全部客戶端(在使用多個 node 實例的狀況下)
  io.local.emit('hi', 'my lovely babies');

};

提示: 下面的事件是保留的,不該該在應用中用做事件名稱:

  • error
  • connect
  • disconnect
  • disconnecting
  • newListener
  • removeListener
  • ping
  • pong

相關文章:
socket.io 快速入門教程——聊天應用
Java SocketIO實現消息推送

相關文章
相關標籤/搜索