async init() {
this.socket = await this.connentSocket()
return this
}
async connentSocket() {
if (this.socket) return this.socket
return new Promise((resolve, reject) => {
let socket = io(this.host, { path: this.socketPath })
socket.on(“connect”, () => {
console.log(“连接成功!”)
resolve(socket)
})
socket.on(“connect_error”, e => {
console.log(“连接失败!”)
throw e
reject()
})
// 呼叫被接受
socket.on(‘answer’, ({ answer }) => {
this.peer && this.peer.setRemoteDescription(answer)
})
// 被呼叫事件
socket.on(‘called’, callingInfo => {
this.called && this.called(callingInfo)
})
// 呼叫被拒
socket.on(‘callRejected’, () => {
this.getCallReject && this.getCallReject()
})
socket.on(‘iceCandidate’, ({ iceCandidate }) => {
console.log(‘远端添加iceCandidate’);
this.peer && this.peer.addIceCandidate(new RTCIceCandidate(iceCandidate))
})
})
}
addEvent(name, cb) {
if (!this.socket) return
this.socket.on(name, (data) => {
cb.call(this, data)
})
}
sendMessage(name, data) {
if (!this.socket) return
this.socket.emit(name, data)
}
// 获取本地媒体流
async getLocalMedia() {
let localMedia = await navigator.mediaDevices
.getUserMedia({ video: { facingMode: “user” }, audio: true })
.catch(e => {
console.log(e)
})
this.localMedia = localMedia
return this
}
// 设置媒体流到video
setMediaTo(eleId, media) {
document.getElementById(eleId).srcObject = media
}
// 被叫响应
called(callingInfo) {
this.calledHandle && this.calledHandle(callingInfo)
}
// 创建RTC
createLoacalPeer() {
this.peer = new RTCPeerConnection()
return this
}
// 将媒体流加入通信
addTrack() {
if (!this.peer || !this.localMedia) return
//this.localMedia.getTracks().forEach(track => this.peer.addTrack(track, this.localMedia));
this.peer.addStream(this.localMedia)
return this
}
// 创建 SDP offer
async createOffer(cb) {
if (!this.peer) return
let offer = await this.peer.createOffer({ OfferToReceiveAudio: true, OfferToReceiveVideo: true })
this.peer.setLocalDescription(offer)
cb && cb(offer)
return this
}
async createAnswer(offer, cb) {
if (!this.peer) return
this.peer.setRemoteDescription(offer)
let answer = await this.peer.createAnswer({ OfferToReceiveAudio: true, OfferToReceiveVideo: true })
this.peer.setLocalDescription(answer)
cb && cb(answer)
return this
}
listenerAddStream(cb) {
this.peer.addEventListener(‘addstream’, event => {
console.log(‘addstream事件触发’, event.stream);
cb && cb(event.stream);
})
return this
}
// 监听候选加入
listenerCandidateAdd(cb) {
this.peer.addEventListener(‘icecandidate’, event => {
let iceCandidate = event.candidate;
if (iceCandidate) {
console.log(‘发送candidate给远端’);
cb && cb(iceCandidate);
}
})
return this
}
// 检测ice协商过程
listenerGatheringstatechange () {
this.peer.addEventListener(‘icegatheringstatechange’, e => {
console.log('ice协商中: ', e.target.iceGatheringState);
})
return this
}
// 关闭RTC
closeRTC() {
// …
}
}
const SocketIO = require(‘socket.io’)
const socketIO = new SocketIO({
path: ‘/websocket’
})
let userRoom = {
list: [],
add(user) {
this.list.push(user)
return this
},
del(id) {
this.list = this.list.filter(u => u.id !== id)
return this
},
sendAllUser(name, data) {
this.list.forEach(({ id }) => {
console.log(‘>>>>>’, id)
socketIO.to(id).emit(name, data)
})
return this
},
sendTo(id) {
return (eventName, data) => {
socketIO.to(id).emit(eventName, data)
}
2.后端
const SocketIO = require(‘socket.io’)
const socketIO = new SocketIO({
path: ‘/websocket’
})
let userRoom = {
list: [],
add(user) {
this.list.push(user)
return this
},
del(id) {
this.list = this.list.filter(u => u.id !== id)
return this
},
sendAllUser(name, data) {
this.list.forEach(({ id }) => {
console.log(‘>>>>>’, id)
socketIO.to(id).emit(name, data)
})
return this
},
sendTo(id) {
return (eventName, data) => {
socketIO.to(id).emit(eventName, data)
}
},
findName(id) {
return this.list.find(u => u.id === id).name
}
}
socketIO.on(‘connection’, function(socket) {
console.log(‘连接加入.’, socket.id)
socket.on(‘addUser’, function(data) {
console.log(data.name, ‘加入房间’)
let user = {
id: socket.id,
name: data.name,
calling: false
}
userRoom.add(user).sendAllUser(‘updateUserList’, userRoom.list)
})
socket.on(‘sendMessage’, ({ content }) => {
console.log(‘转发消息:’, content)
userRoom.sendAllUser(‘updateMessageList’, { userId: socket.id, content, user: userRoom.findName(socket.id) })
})
socket.on(‘iceCandidate’, ({ id, iceCandidate }) => {
console.log(‘转发信道’)
userRoom.sendTo(id)(‘iceCandidate’, { iceCandidate, id: socket.id })
})
socket.on(‘offer’, ({id, offer}) => {
console.log(‘转发offer’)
userRoom.sendTo(id)(‘called’, { offer, id: socket.id, name: userRoom.findName(socket.id)})
})
socket.on(‘answer’, ({id, answer}) => {
console.log(‘接受视频’);
userRoom.sendTo(id)(‘answer’, {answer})
})
socket.on(‘rejectCall’, id => {
console.log(‘转发拒接视频’)
userRoom.sendTo(id)(‘callRejected’)
})
socket.on(‘disconnect’, () => {
// 断开删除
console.log(‘连接断开’, socket.id)
userRoom.del(socket.id).sendAllUser(‘updateUserList’, userRoom.list)
})
})
module.exports = socketIO
// www.js 这就不关键了
const http = require(‘http’)
const app = require(‘…/app’)
const socketIO = require(‘…/socket.js’)
const server = http.createServer(app.callback())
socketIO.attach(server)
server.listen(3003, () => {
console.log(‘server start on 127.0.0.1:3003’)
})
搭建 STUN/TURN
因为没有钱买服务器 没试过
coturn 据说使用它搭建 STUN/TURN 服务非常的方便
编译
cd coturn
./configure --prefix=/usr/local/coturn
sudo make -j 4 && make install
配置
listening-port=3478 #指定侦听的端口
external-ip=39.105.185.198 #指定云主机的公网IP地址
user=aaaaaa:bbbbbb #访问 stun/turn服务的用户名和密码
realm=stun.xxx.cn #域名,这个一定要设置
#启动
cd /usr/local/coturn/bin
turnserver -c …/etc/turnserver.conf
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://img-blog.csdnimg.cn/img_convert/5f0fa36c3a4bf533a0a567d74610304c.jpeg)
最后
给大家分享一些关于HTML的面试题,有需要的朋友可以戳这里获取,先到先得哦。
真正体系化!**
[外链图片转存中…(img-RHUQIvOA-1712797611242)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://img-blog.csdnimg.cn/img_convert/5f0fa36c3a4bf533a0a567d74610304c.jpeg)
最后
给大家分享一些关于HTML的面试题,有需要的朋友可以戳这里获取,先到先得哦。
[外链图片转存中…(img-UJ5Xq77z-1712797611242)]
[外链图片转存中…(img-SOqFwcfZ-1712797611242)]