技术前言

通过前几次教程已经可以轻松的实现两个浏览器之间的文本信令交互和视频对讲功能。本次课程要融合以前所有技术点,做一次综合性实例,采用nodejs实现一个完整的聊天室功能。其界面样式仿照微信的界面搭建。

接口方法

在此我根据实例代码用到的接口做如下讲解,为了方便本实例我们采用nodejs开发,其中用到了socket.io技术。如果对socket.io(https://socket.io/)不明白的话可以先学习一下socket.io再回来看本教程。
1. io.sockets.on(‘connection’, function (socket) {});
消息连接方法,其中回调函数的socket参数为一个client与服务器的连接标识,不同的client会有不同的连接标识。
2. socket.emit(‘message’, “this is a test”);
向所有已连接服务器的终端也包括自己在内广播消息"this is a test"。
3. socket.broadcast.emit(‘message’, “this is a test”);
向除了自己所有已连接服务器的socket终端广播消息"this is a test"
4. socket.broadcast.to(‘game’).emit(‘message’, ‘nice game’);
向game房间中除了自己的所有终端广播消息"this is a test"
5. io.sockets.in(‘game’).emit(‘message’, ‘cool game’);
向game房间中包括自己在内的所有终端广播消息"this is a test"
sending to individual socketid
6. io.sockets.socket(socketid).emit(‘message’, ‘for your eyes only’);
仅给连接编号为socketid的终端发送消息
7. io.sockets.on(‘xx’,function);
以‘xx‘为协义订阅服务端的消息通知事件。

实践代码

前端界面
index.jade

extends layout
title=abc
block headerlink(rel='stylesheet', href='/stylesheets/reset.min.css')script(src = "/javascripts/trace.js")script(src = "/javascripts/config.js")script(src = "/javascripts/socket.io.js")script(src="/javascripts/jquery-1.11.1.min.js")script(src="/javascripts/Tdrag.js")script(src = "/javascripts/jquerysocketio.js")script(src="../javascripts/index/index.js")block contenth1 SocketIo Server Web1p Welcome to SocketIo Server Web

index.html

<style type="text/css">#localVideo {background-color: #999999;border: 1px #999999 solid;width: 100%;height: 100%;}#remoteVideo {position: relative;float: left;top: -395px;left: 5px;background-color: black;width: 150px;height: 150px;text-align: center;z-index: 1;}.vbtn{position: relative;top: -90px;}.vbtn img{width: 64px;height: 64px;}.video {position: absolute;display: none;top:150px;left: 250px;border: 1px black solid;width: 450px;height: 400px;}.talk a:link {color: white;}.span {position: relative;padding: 5px;}.tip {display: block;background: #f00;border-radius: 50%;width: 8px;height: 8px;top: 0px;right: 0px;position: absolute;}
</style><div class="wrapper"><div class="container"><div class="left"><div class="top"><img src="../images/chat/thomas.jpg" id="headerImg" class="search" alt="" /><span class="name" id="headerName"></span></div><ul class="people"><li class="person" data-chat="person1"><img src="../images/chat/thomas.jpg" alt="" /><span class="name">张三三</span><span class="preview">I was wondering...</span></li><li class="person" data-chat="person2"><img src="../images/chat/dog.png" alt="" /><span class="name">李四四</span><span class="preview">I've forgotten how it felt before</span></li><li class="person" data-chat="person3"><img src="../images/chat/louis-ck.jpeg" alt="" /><span class="name">王五五</span><span class="preview">But we’re probably gonna need a new carpet.</span></li><li class="person" data-chat="person4"><img src="../images/chat/bo-jackson.jpg" alt="" /><span class="name">赵七七</span><span class="preview">It’s not that bad...</span></li><li class="person" data-chat="person5"><img src="../images/chat/michael-jordan.jpg" alt="" /><span class="name">周八皮</span><span class="preview">Wasup for the third time like is
you blind bitch</span></li><li class="person" data-chat="person6"><img src="../images/chat/drake.jpg" alt="" /><span class="name">李寻欢</span><span class="preview">howdoyoudoaspace</span></li></ul></div><div class="right"><div class="top"><span>To: <span class="name" id="friendName">暂无好友</span></span></div><div class="chat" data-chat="person1"></div><div class="chat" data-chat="person2"></div><div class="chat" data-chat="person3"></div><div class="chat" data-chat="person4"></div><div class="chat" data-chat="person5"></div><div class="chat" data-chat="person6"></div><div class="write"><a href="javascript:;" class="write-link attach"></a><input type="text" id="txtContent" /><a href="javascript:;" class="write-link smiley" id="videoBtn"></a><a href="javascript:;" class="write-link send" id="sendBtn"></a></div></div></div>
</div><div id="video" class="video"><video id="localVideo" autoplay playsinline></video><video id="remoteVideo" autoplay playsinline></video><div class="vbtn"><img src="../images/call_0.png" id="CloseBtn"  /></div></div>

服务端


var app = express();
app.listen(6000);var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(6100);var persons = [];
var getPersonSeq = function() {var tempSeq = Math.floor(Math.random() * 5) + 1;persons.forEach(p => {if (p.seq == tempSeq) {tempSeq = getPersonSeq();}});return tempSeq;
}
io.sockets.on('connection', function(socket) {if (persons.indexOf(socket.id) == -1) {persons.push({id: socket.id,seq: getPersonSeq()});}function trace() {console.log(arguments);}console.log("用户 '" + socket.id + "' 连接成功!");socket.emit('ready', socket.id, persons);socket.broadcast.emit('change', persons);socket.on('disconnect', function() {trace('终端(' + socket.id + ')已断开。 ');var tempPersons = [];persons.forEach(e => {if (e.id != socket.id) {tempPersons.push(e);}});persons = tempPersons;//rooms.del(socket.id);socket.broadcast.emit('change', persons);});socket.on('message', function(body) {var d = new Date();body.from = socket.id;body.time = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();socket.to(body.to).emit('message', body);trace('终端(' + socket.id + "):message>", body);});socket.on('meeting', function(body) {///向除自己外所有meeting终端广播消息socket.broadcast.emit('meeting', body);//sockets.in(room).emit('meeting', body);trace('终端(' + socket.id + "):meeting>", body);});socket.on('create', function(room, callbackfunc) {var clientsInRoom = io.sockets.adapter.rooms[room];var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;var temproom = {id: room,count: numClients};socket.join(room);//rooms.save(temproom);if (typeof(callbackfunc) == 'function') {callbackfunc(temproom);}});socket.on('join', function(room, callbackfunc) {var clientsInRoom = io.sockets.adapter.rooms[room];var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;var robj = {id: room,count: numClients}switch (numClients) {case 0:trace('终端(' + socket.id + ')进入的房间 ”' + room + '" 不存在!');socket.emit('empty', room);break;case 1:///向房间room中发送消息io.sockets.in(room).emit('join', room);socket.join(room);trace('房间 ' + room + '中现在有' + numClients + '个终端!');break;case 2:socket.emit('full', room);trace('房间 ”' + room + '" 已满。');break;}if (typeof(callbackfunc) == 'function') {callbackfunc(robj);}});socket.on('ipaddr', function() {var ifaces = os.networkInterfaces();for (var dev in ifaces) {ifaces[dev].forEach(function(details) {if (details.family === 'IPv4' && details.address !== '127.0.0.1') {socket.emit('ipaddr', details.address);}});}});});

部署发布

本实例代码用nodejs直接发布到服务上,经测试socket.io会发生跨域访问,我们可以通过Nginx实现一个反向代理,由于webrtc视频通讯需要采用https协议访问才能调用视频流,Nginx需要设置ssl配置。
Nginx Https Server 配置如下:

    # HTTPS serverserver {listen       443 ssl;server_name  localhost;ssl_certificate      ca/cert/cre.pem;ssl_certificate_key  ca/cert/cre.key;ssl_session_cache    shared:SSL:1m;ssl_session_timeout  5m;ssl_ciphers  HIGH:!aNULL:!MD5;ssl_prefer_server_ciphers  on;location / {proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host  $http_host;proxy_set_header X-Nginx-Proxy true;proxy_set_header Connection "";proxy_pass http://127.0.0.1:3000;proxy_redirect default;}}

运行结果

不同浏览器之间普通文本内容通讯,左侧选择好友,右侧发送消息。
不同浏览器之间视频实时通讯,左侧选择好友,右侧发送视频邀请。在测试的时候我是用的同一台电脑,所以本地和远程都是相同的图像。

实践历程

1. WebRTC实践简介
2. WebRTC实践获取视频流
3. WebRTC实践传输视频流
4. WebRTC实践信令服务
5. WebRTC实践点对点通信
6. WebRTC实践视频聊天室
7.WebRTC实践总结

WebRTC实践视频聊天室相关推荐

  1. 基于webrtc的视频聊天室(一)之千里之行始于足下

    在不采用流媒体的情况下,也能够实现视频聊天室:可这需要在客户端建立多个连接,对客户端要求很高(上行带宽以及浏览器编解码速度),所以引入 kurento 流媒体服务器来做中转,或许后续不仅仅只是做中转. ...

  2. WebRTC 教程五:WebRTC搭建视频聊天室

    这篇文章主要介绍了 WebRTC 聊天室的整体演示,以及 WebRTC 视频聊天的功能设计,代码逻辑以及整体演示. 目录 WebRTC 聊天室:总体演示 WebRTC 视频聊天: 设计 WebRTC ...

  3. android 使用WebRTC搭建视频聊天室

    使用WebRTC搭建前端视频聊天室--入门篇 https://www.jianshu.com/p/b54b27970534 android webrtc 两个手机 P2P 视频聊天 https://w ...

  4. 基于webrtc的视频聊天室(五)之服务端设计

    组件的描述已在前几个博文中给出.下面针对具体的流程给出详细描述. 如何进行sdp协商 建立任何聊天都需要保证服务端有相应的 WebRtc 对象,当然,客户端也需要建立对应的 WebRtc 对象,它们之 ...

  5. 基于webrtc的视频聊天室(六)之客户端设计

    客户端用 Vue 框架写的,分了8个自定义组件: container.vue 是其它组件的父组件,其中 WebRtcPeerSendRecv.vue 是共用组件,UserOpt 和OneToOneBo ...

  6. WebRTC笔记之二十二:基于WebRTC的视频聊天室—QHTalkGenius

    利用空余时间,前后历时5个月,在公司大佬杰哥的指导下,QHTalkJanus终于搞定了.功能很简单,参考Janus的web客户端来做的,主要实现了三部分:1.Janus信令解析-这个用的是开源库Web ...

  7. 基于webrtc的视频聊天室(四)之用户设计

    用户的设计主要是明确其生命周期及其需要持有的对象. 用户的生命周期 创建 websocket连接时,建立普通用户对象: 申请通话时,等待对方响应: 对方接受,如果为群组聊天,则将其更改为 GroupU ...

  8. 如何使用野狗搭建视频聊天室-WebRTC的技术实践

    原文  https://blog.wilddog.com/?p=1354 主题 WebRTC 作者:潘嘉明 野狗科技嵌入式工程师,曾在TP-Link从事相关工作,在嵌入式研究上经验丰富. 一直以来,因 ...

  9. 使用WebRTC搭建前端视频聊天室——数据通道篇

    转自 使用WebRTC搭建前端视频聊天室--数据通道篇 在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩 ...

最新文章

  1. 工作总结的写作方法与要领
  2. matlab 传递函数 响应,matlab:知道传递函数G,怎么画出阶跃响应?
  3. TensorFlow tf.keras.losses.CategoricalCrossentropy
  4. ireport设置当前页面纸张大小格式:为何每次右键显示的可选项不一样
  5. dojo uploader使用,ps.返回值
  6. Opencv3 Robert算子 Sobel算子 拉普拉斯算子 自定义卷积核——实现渐进模糊
  7. javscript DOM基础知识(常用篇)
  8. 浏览器中performance的基本使用
  9. 【网络安全】黑客攻防与入侵检测(练习题)
  10. 小程序 40163_小程序获取openid 出现null,{errcode:40163,errmsg:code been used, hints: [ req_id: WNUzlA0105t...
  11. Xcode可以清理哪些缓存?
  12. 科技传播杂志科技传播杂志社科技传播编辑部2022年第9期目录
  13. 7-4 疯狂星期四!!!!!
  14. win2008r2用户账户控制什么意思_养老保险统筹账户是什么意思?有什么用?
  15. 程序员的爱情 第十七章
  16. 记录Guava版本冲突而出现项目启动失败的问题
  17. pycharm设置中文,字体颜色修改,设置背景图片(图文讲解)
  18. 顾盼华发鸿蒙怦然而梦是什么意思,最美的承诺情话
  19. 密室寻宝(find)
  20. 通用型简单latex模板&表格制作

热门文章

  1. 香港第一金:美债上升美元走强 黄金暴跌下破199
  2. 游戏 编程 怎么能够深入学习
  3. weex java_weex开发
  4. java中socket被拒绝_JavaMail API到iMail – java.net.SocketException:权限被拒绝:连接...
  5. tta部署_TTA、丰源轮胎云平台项目合作交接仪式
  6. Vue+ElementUI 之 input输入框 添加自定义图片
  7. FPGA之4K图像处理
  8. Linux 系统安全与优化配置
  9. 一文搞懂 HTTP 的长连接和短连接
  10. 科大讯飞也推AI智能硬件,K12“知识图谱型”AI教育“真香”?