Socket.io服务端对象
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server); //服务端的Socket.io对象
Socket.io客户端对象
<!-- 需要加载socket.io客户端第三方库 -->
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script>
const socket = io(); //Socket.io客户端对象
</script>
socket.io事件
- socket.io服务器的系统事件
- io.on(‘connection’, callback): 有新Socket连接建立时
- socket.on(‘message’, callback): 当有socket..send()方法发送完信息后触发
- socket.on(‘disconnect’, callback): 当连接断开时触发
- 客户端的系统事件
- socket.io.on(‘open’, callback): 当socket客户端开启与服务器的新连接时触发
- socket.io.on(‘connect’, callback):当socket客户端连接到服务器后触发
- socket.io.on(‘connect_timeout’, callback):当socket客户端与服务器连接超时后触发
- socket.io.on(‘connec_errort’, callback):当socket客户端连接服务器失败时触发
- socket.io.on(‘connec_attemptt’, callback):当socket客户端尝试重新连接到服务器后触发
- socket.io.on(‘reconnect’, callback):当socket客户端重新连接到服务器后触发
- socket.io.on(‘reconnect_error’, callback):当socket客户端重新连接服务器失败后触发
- socket.io.on(‘reconnect_fail’, callback):当socket客户端重新连接到服务器失败后触发
- socket.io.on(‘close’, callback):当socket客户端关闭与服务器的连接后触发
- socket.io服务器的系统事件
事件触发
- 服务端触发
- 客户端触发
/*服务端*/
io.on('connection', function (socket) {
socket.emit('customEvent', message);
});
<!--客户端-->
<script>
var socket = io();
socket.emit('customEvent', mesaage);
</script>
- 事件处理
/*服务端*/
io.on('connection', function (socket) {
socket.on('customEvent', (message) => {
/*逻辑代码*/
}
});
//通过broadcast属性可以给处理当前连接外的所有连接的socket客户端发送事件:
io.on('connection',(socket)=>{
socket.broadcast.emit('customEvent', meassage);
});
<!--客户端-->
<script>
var socket =io();
socket.on('eventName',(message)=>{
/逻辑代码*/
});
</script>
- socket.io命名空间:对socker连接进行划分命名空间,可以对不同的socket的连接分类管理,而且不需要新建socket服务器实例.
//服务端命名空间
io.of('/someNameSpace').on('connection', (socket)=>{
socket.on('customEvent', (message)=>{
/*逻辑代码*/
});
});
<!--客户端命名空间-->
<script>
var someSocket = io('/someNameSpace');
someSocket.on('customEvent', (message)=>{
/*逻辑代码*/
});
</script>
- Socket.io的房间:房间功能动态的对已连接的socket进行分组.socket连接可以加入和离开房间
io.on('connection', (socket)=>{ //加入房间
socket.on('join', (roomData)=>{
socket.join(roomData.roomName);
});
socket.on('leave', (roomData)=>{ //离开房间
socket.leave(roomData.roomName);
});
});
//房间中触发事件
io.on('connection', (socket)=>{ //对房间所有socket连接
io.in('someRoom').emit('customEvent', message);
});
//对房间内除了当前连接外的socket触发事件
io.on('connection', (socket)=>{ //对房间所有socket连接
io.broadcast.to('someRoom').emit('customEvent', message);
});
- 服务端:使用了express框架搭建,socket.io将借住express服务来实现用户验证,同步会话;
express.js
/*socket.io实时通讯的使用*/
const socketio = require('socket.io'),
http = require('http'),
MongoStore = require('connect-mongo')(session); //当作会话数据储存
module.exports = function() {
var server = http.createServer(app); //使用新的server替换以前的express应用对象
var io = socketio.listen(server); //将soket.io服务附加给server
//创建MonggoStore的实例,并传入了Mongoose的连接对象
var mongoStore = new MongoStore({
url: config.db
});
app.use(session({ //配置session,存储到mongo数据库中
saveUninitialized: false, //是否自动保存未初始化的会话,建议false
resave: false, //是否每次都重新保存会话,建议false
secret: config.sessionSecret,
store: mongoStore,
cookie: {
maxAge: config.minute
}
}));
require('./socketio')(server, io, mongoStore); //为server和io,配置处理客户端信息的处理
}
socketio.js
'use strict';
var config = require('./config'),
cookieParser = require('cookie-parser'),
passport = require('passport');
module.exports = function (server, io, mongoStore) {
io.use(function (socket, next) {
//使用cookieParser来解析握手请求中的cookie,并且获取对应express中的sessionId
cookieParser(config.sessionSecret)(socket.request, {}, function (err) {
var sessionId = socket.request.signedCookies['connect.sid'];
//使用mongoStore检索会话信息
mongoStore.get(sessionId, function (err, session) {
socket.request.session = session;
//一旦检索到就用passport.initialize()和passport.session()中间件根据会话
//信息来填充会话的user对象
passport.initialize()(socket.request, {}, function () {
passport.session()(socket.request, {}, function () {
if(socket.request.user) {
next(null, true);
} else {
next(new Error('User is not authenticated'), false);
}
});
});
});
});
});
io.on('connection', function (socket) { //监听新连接,有的话调用处理函数
require('../app/controllers/chat.server.controller')(io, socket);
});
};
chat.server.controller.js
'use strict';
module.exports = function (io, socket) {
io.emit('chatMessage', { //通过io对象向所有监听'chatMessage'事件的客户端发送消息
type: 'status',
text: 'connencted',
created: Date.now(),
username: socket.request.user.username
});
socket.on('chatMessage', (message) => { //监听socket客户端'chatMeaasge'事件
message.type = 'message';
message.created = Date.now();
message.username = socket.request.user.username;
io.emit('chatMessage', message);
});
socket.on('disconnect', () => { //监听socket客户端与服务器断开建立的事件,并且触发回调
io.emit('chatMessage', {
type: 'status',
text: 'disconnected',
created: Date.now(),
username: socket.request.user.username
});
});
};
- 客户端:使用的是Angular1.x的前端框架
chat.client.service.js
angular.module('chat').service('Socket', ['Authentication', '$location', '$timeout',
function (Authentication, $location, $timeout) {
if(Authentication.user) { //判断是否有用户登陆
this.socket = io();
} else {
$location.path('/');
}
this.on = function (eventName, callback) { //监听evetName事件
if(this.socket) { //判断io()是否实例化;
this.socket.on(eventName, function (data) {
$timeout(function () { //socket客户端是第三方库,需要用$timeout触发Angular的绑定操作
callback(data);
});
});
}
}
this.emit = function (eventName, data) { //触发eventName事件
if(this.socket) {
this.socket.emit(eventName, data);
}
}
this.removeListener = function (eventName) { // 取消eventName事件监听
if(this.socket) {
this.socket.emit(eventName);
}
}
}]);
chat.client.controller.js
angular.module('chat')
.controller('ChatController', ['$scope', 'Socket',
function ($scope, Socket) {
var self = this;
$scope.messages = [];
Socket.on('chatMessage', function (message) {
$scope.messages.push(message);
});
$scope.sendMessage = function () {
console.log(self.messageText);
var message = {
text: self.messageText,
}
Socket.emit('chatMessage', message);
self.messageText = '';
}
$scope.destory = function () { //离开聊天室
Socket.removeListener('chatMessage');
}
}]);
index.html
<!-- 需要加载socket.io客户端第三方库 -->
<script type="text/javascript" src="/socket.io/socket.io.js"></script>