1、什么是scoketio?
由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验,于是socket.io诞生。
Socket.IO包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。
2、本质
Socket.io将Websocket和轮询 (Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。也就是说,Websocket仅仅是 Socket.io实现实时通信的一个子集。
它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5,应该可以满足绝大部分需求了。
3、socket的组成
Socket.IO 由两部分组成:
1.一个服务端用于集成 (或挂载) 到 Node.JS HTTP 服务器: socket.io
2.一个加载到浏览器中的客户端: socket.io-client
3.开发环境下, socket.io 会自动提供客户端。
4、socket的基本使用
提示:由于开发环境下, socket.io 会自动提供客户端。所以我们只需要安装一个socket.io模块即可。
① 新建一个package.json文件
npm init --yes
② 安装express与socket.io模块
cnpm i express socket.io -S
5、群聊实现
后端代码
let app = require("express")();// 获取express模块实例
let http = require('http').Server(app);// 将express模块实例作为回调构建http模块实例
let io = require('socket.io')(http);// 将http模块实例作为回调构建socket.io模块实例
// 使用http模块开启后端服务(原生node+express的结合)
http.listen(3000, function () {
console.log('listening on http://127.0.0.1:3000')
})
//设置路由,构建后端接口
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
})
// 开始监听前端的socket请求连接(前端每次执行一次io()方法就就会发起一次socket请求)
io.on('connection',function(socket){
console.log('a user connected');
// 接收客户端发来的数据
socket.on('chat message',function(msg){
console.log('message:'+msg);
io.emit('receiveMessage',msg)
})
// 如果是断开socket请求,就会触发下面的代码
socket.on('disconnect',function(){
console.log('user disconnect')
})
})
前端代码
<!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: 80%;
margin-right: .5%;
}
form button {
width: 19%;
background: rgb(130, 224, 255);
border: none;
padding: 10px;
}
#messages {
list-style-type: none;
margin: 0;
padding: 0;
}
#messages li {
padding: 5px 10px;
}
</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>
// 这样就加载了 socket.io-client。 socket.io-client 暴露了一个 io 全局变量,然后连接服务器。
//请注意我们在调用 io() 时没有指定任何 URL,因为它默认将尝试连接到提供当前页面的主机。
var username = prompt('请输入用户名')
var socket = io('http://localhost:3000');
var form = document.querySelector('form');
var val = document.querySelector('#m');
// var messages=document.querySelector('#messages')
form.onsubmit = function () {
var obj = {
username: username,
mes: val.value
}
socket.emit('chat message', JSON.stringify(obj));
messages.innerHTML += `
<li style="text-align:right;color:blue;">${val.value}<li>
`;
val.value = '';
return false;//阻止表单默认行为
}
//接收后端发来的消息
socket.on('receiveMessage', function (data) {
var obj = JSON.parse(data);
if (obj.username == username)
//不渲染自己发送的消息
return;
//渲染别人发送的消息
messages.innerHTML += `
<li style="text-align:left;color:red;">${obj.username}:${obj.mes}<li>`;
})
</script>
</html>
效果
6、私聊
后端
var app = require('express')(); // 获取express模块实例
var http = require('http').Server(app); // 将express模块实例作为回调构建http模块实例
var io = require('socket.io')(http); // 将http模块实例作为回调构建socket.io模块实例
// 使用http模块开启后端服务(原生node+express的结合)
http.listen(3000, function () {
console.log('listening on http://127.0.0.1:3000')
})
// 设置路由,构建后端接口
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html'); // 将根目录下的index.html发送到前端
})
var users = {}; // 保存所有用户的键值对集合
io.on('connection', function (socket) {
socket.on('con', function (msg) {
var obj = JSON.parse(msg) // 获取连接的用户信息
users[obj.username] = socket.id; // 将当前用户名和对应的链接id进行保存
console.log('有新的链接,最新用户集合为:', users)
})
// 接收客户端发来的数据
socket.on('chat message', function (msg) {
var obj = JSON.parse(msg) // 获取连接的用户信息
console.log('obj:', obj)
if (users[obj.toWho] == undefined) {
let respmes = {
usernamez: '系统信息',
mes: '抱歉【' + obj.toWho + '】还未上线'
}
io.to(socket.id).emit('receiveMessage', JSON.stringify(respmes)); // 将消息发给当前用户
} else { // 说明目标用户存在
let respmes = {
usernamez: obj.username,
mes: obj.mes
}
io.to(users[obj.toWho]).emit('receiveMessage', JSON.stringify(respmes)); // 通过id将信息转发给指定的对象
}
})
// 如果是断开socket请求,就会触发下面的代码
socket.on('disconnect', function () {
console.log('user disconnected')
})
})
前端
<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: 80%;
margin-right: .5%;
}
form button {
width: 19%;
background: rgb(130, 224, 255);
border: none;
padding: 10px;
}
#messages {
list-style-type: none;
margin: 0;
padding: 0;
}
#messages li {
padding: 5px 10px;
}
</style>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
// 这样就加载了 socket.io-client。 socket.io-client 暴露了一个 io 全局变量,然后连接服务器。
//请注意我们在调用 io() 时没有指定任何 URL,因为它默认将尝试连接到提供当前页面的主机。
window.onload = function () {
var username = prompt("请输入你的用户名:", "");
var who = prompt("你要和谁聊天?:", "");
document.body.innerHTML = `<h3>当前用户:${username}, 和${who}聊天中...</h3>` + document.body.innerHTML;
var socket = io("http://localhost:3000/");
var form = document.querySelector("form");
var val = document.querySelector("#m");
//先和服务端建立连接
let conobj = {
username: username,
toWho: who,
}
socket.emit('con', JSON.stringify(conobj));
//表单提交事件
form.onsubmit = function () {
let obj = {
username: username,
toWho: who,
mes: val.value
}
socket.emit('chat message', JSON.stringify(obj));
messages.innerHTML += `
<li style="text-align:right;color:blue;">${val.value}<li>`;
val.value = "";
return false;
}
//接收后端发来的消息
socket.on("receiveMessage", function (data) {
var obj = JSON.parse(data);
console.log(obj)
if (obj.username == username) return; //不接受自己发的消息
messages.innerHTML += `
<li style="text-align:left;color:red;">${obj.usernamez}:${obj.mes}<li>`;
})
}
</script>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>
效果