一、基本概念
Socket.IO 是一个基于 Node.js 的实时应用程序框架,在即时通讯、通知与消息推送,实时分析等场景中有较为广泛的应用。
WebSocket 的产生源于 Web 开发中日益增长的实时通信需求,对比基于 http 的轮询方式,它大大节省了网络带宽,同时也降低了服务器的性能消耗; socket.io 支持 websocket、polling 两种数据传输方式以兼容浏览器不支持 WebSocket 场景下的通信需求。
WebSocket是HTML5最新提出的规范,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况,为了兼容所有浏览器,给程序员提供一致的编程体验,SocketIO将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,我们在使用SocketIO时,不用担心兼容问题,底层会自动选用最佳的通信方式。因此说,WebSocket是SocketIO的一个子集。
二、应用
首先要制作一个 HTML 页面来提供表单和消息列表。我们使用了基于 Node.JS 的 web 框架 express
。 请确保安装了 Node.JS。
首先创建一个 package.json
来描述我们的项目。 推荐新建一个空目录 (这里使用 chat-example
)。
{
"name": "socket-chat-example",
"version": "0.0.1",
"description": "my first socket.io app",
"dependencies": {}
}
安装相关依赖:
npm install --save express@4.15.2
npm install --save socket.io
前端页面:
index.html
<!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:
// 1、Express 初始化 app 作为 HTTP 服务器的回调函数
var app = require('express')();
var http = require('http').Server(app)
var io = require('socket.io')(http);
// 2、定义了一个路由 / 来处理首页访问。
/*
app.get('/', function(req, res){
res.send('<h1>Hello world</h1>');
});
*/
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
// 3、使 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);
});
});
启动服务:
dell@DESKTOP-KPEE6OO MINGW64 /C/work/other/socket-chat
$ node index.js
listening on *:3000
访问界面:
三、升级版
先看界面:
服务端 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
四、事件速查表
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官方示例
socket.io 快速入门教程——聊天应用
Java SocketIO实现消息推送
WebRTC 入门教程(一)| 搭建WebRTC信令服务器
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。