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>
效果