老同学十块钱让我帮做个视频网站,带弹幕那种

news/2024/5/13 2:02:12/文章来源:https://blog.csdn.net/Y0Q2T57s/article/details/120397510

Java面试笔试面经、Java技术每天学习一点

19a0d3c29fefdbedd2c7e197e5657a36.png

公众号Java面试

关注我不迷路

作者:刘滨浩

来源:https://binhao.blog.csdn.net/

0b6ba6441d142efc3ead9ff14215b754.png

2021年了,还有不支持弹幕的视频网站吗,现在各种弹幕玩法层出不穷,抽奖,ppt都上弹幕玩法了,不整个弹幕都说不过去了,今天笔者就抽空做了一个实时视频弹幕交互功能的实现,不得不说这样的形式为看视频看直播,讲义PPT,抽奖等形式增加了许多乐趣。

1 技术选型

1.1 netty

官方对于netty的描述:

https://netty.io/

主要关键词描述:netty是异步事件驱动网络框架,可做各种协议服务端,并且支持了FTP,SMTP,HTTP等很多协议,并且性能,稳定性,灵活性都很棒。

81a7ff4074822513be10bec95cc735fd.png

可以看到netty整体架构上分了三个部分:

  • 以零拷贝,一致性接口,扩展事件模型的底层核心。

  • Socket,Datagram,Pipe,Http Tunnel作为传输媒介。

  • 传输支持的各种协议,HTTP&WebSocket,SSL,大文件,zlib/gzip压缩,文本,二进制,Google Protobuf等各种各种的传输形式。

1.2 WebSocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

1.3 为什么做这样的技术选型。

  • 由上述可知,实时直播交互作为互动式是一个双向数据传输过程。所以使用webSocket。

  • netty本身支持了webSocket协议的实现,让实现更加简单方便。

2 实现思路

2.1 服务架构

整体架构是所有客户端都和我的服务端开启一个双向通道的架构。

9a1237dcdaa9777dc67ae8ce8dc5e427.png

2.2 传输流程

5fa66b1ec569d66b1599cd3cffc7fcee.png

3 实现效果

3.1 视频展示

先看看效果吧,是不是perfect,接下来就来看具体代码是怎么实现的吧。

3c4f19f89e892a9d68a33bbd9078b8da.png
视频直播弹幕示例

4 代码实现

4.1 项目结构

一个maven项目,将代码放一个包下就行。

5a439e09f0129d29d992c837c2b7fc6e.png

4.2 Java服务端

Java服务端代码,总共三个类,Server,Initailizer和 Handler。

4.2.1 先做一个netty nio的服务端:

一个nio的服务,开启一个tcp端口。

/*** Copyright(c)lbhbinhao@163.com* @author liubinhao* @date 2021/1/14* ++++ ______                           ______             ______* +++/     /|                         /     /|           /     /|* +/_____/  |                       /_____/  |         /_____/  |* |     |   |                      |     |   |        |     |   |* |     |   |                      |     |   |________|     |   |* |     |   |                      |     |  /         |     |   |* |     |   |                      |     |/___________|     |   |* |     |   |___________________   |     |____________|     |   |* |     |  /                  / |  |     |   |        |     |   |* |     |/ _________________/  /   |     |  /         |     |  /* |_________________________|/b    |_____|/           |_____|/*/
public enum BulletChatServer {/*** Server instance*/SERVER;private BulletChatServer(){EventLoopGroup mainGroup = new NioEventLoopGroup();EventLoopGroup subGroup  = new NioEventLoopGroup();ServerBootstrap server = new ServerBootstrap();server.group(mainGroup,subGroup).channel(NioServerSocketChannel.class).childHandler(new BulletChatInitializer());ChannelFuture future = server.bind(9123);}public static void main(String[] args) {}}

4.2.2 服务端的具体处理逻辑

/*** Copyright(c)lbhbinhao@163.com** @author liubinhao* @date 2021/1/14* ++++ ______                           ______             ______* +++/     /|                         /     /|           /     /|* +/_____/  |                       /_____/  |         /_____/  |* |     |   |                      |     |   |        |     |   |* |     |   |                      |     |   |________|     |   |* |     |   |                      |     |  /         |     |   |* |     |   |                      |     |/___________|     |   |* |     |   |___________________   |     |____________|     |   |* |     |  /                  / |  |     |   |        |     |   |* |     |/ _________________/  /   |     |  /         |     |  /* |_________________________|/b    |_____|/           |_____|/*/public class BulletChatInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new HttpServerCodec());pipeline.addLast(new ChunkedWriteHandler());pipeline.addLast(new HttpObjectAggregator(1024*64));pipeline.addLast(new IdleStateHandler(8, 10, 12));pipeline.addLast(new WebSocketServerProtocolHandler("/lbh"));pipeline.addLast(new BulletChatHandler());}
}

后台处理逻辑,接受到消息,写出到所有的客户端:

/*** Copyright(c)lbhbinhao@163.com** @author liubinhao* @date 2021/1/14* ++++ ______                           ______             ______* +++/     /|                         /     /|           /     /|* +/_____/  |                       /_____/  |         /_____/  |* |     |   |                      |     |   |        |     |   |* |     |   |                      |     |   |________|     |   |* |     |   |                      |     |  /         |     |   |* |     |   |                      |     |/___________|     |   |* |     |   |___________________   |     |____________|     |   |* |     |  /                  / |  |     |   |        |     |   |* |     |/ _________________/  /   |     |  /         |     |  /* |_________________________|/b    |_____|/           |_____|/*/public class BulletChatHandler  extends SimpleChannelInboundHandler<TextWebSocketFrame> {// 用于记录和管理所有客户端的channelpublic static ChannelGroup channels =new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {// 获取客户端传输过来的消息String content = msg.text();System.err.println("收到消息:"+ content);channels.writeAndFlush(new TextWebSocketFrame(content));System.err.println("写出消息完成:"+content);}@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {channels.add(ctx.channel());}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {String channelId = ctx.channel().id().asShortText();System.out.println("客户端被移除,channelId为:" + channelId);channels.remove(ctx.channel());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();// 发生异常之后关闭连接(关闭channel),随后从ChannelGroup中移除ctx.channel().close();channels.remove(ctx.channel());}}

4.3 网页客户端实现

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Netty视频弹幕实现 Author:Binhao Liu</title><link rel="stylesheet" href=""><style type="text/css" media="screen">* {margin: 0px;padding: 0px}html, body {height: 100%}body {overflow: hidden;background-color: #FFF;text-align: center;}.flex-column {display: flex;flex-direction: column;justify-content: space-between;, align-items: center;}.flex-row {display: flex;flex-direction: row;justify-content: center;align-items: center;}.wrap {overflow: hidden;width: 70%;height: 600px;margin: 100px auto;padding: 20px;background-color: transparent;box-shadow: 0 0 9px #222;border-radius: 20px;}.wrap .box {position: relative;width: 100%;height: 90%;background-color: #000000;border-radius: 10px}.wrap .box span {position: absolute;top: 10px;left: 20px;display: block;padding: 10px;color: #336688}.wrap .send {display: flex;width: 100%;height: 10%;background-color: #000000;border-radius: 8px}.wrap .send input {width: 40%;height: 60%;border: 0;outline: 0;border-radius: 5px 0px 0px 5px;box-shadow: 0px 0px 5px #d9d9d9;text-indent: 1em}.wrap .send .send-btn {width: 100px;height: 60%;background-color: #fe943b;color: #FFF;text-align: center;border-radius: 0px 5px 5px 0px;line-height: 30px;cursor: pointer;}.wrap .send .send-btn:hover {background-color: #4cacdc}</style>
</head>
<script>var ws = new WebSocket("ws://localhost:9123/lbh");ws.onopen = function () {// Web Socket 已连接上,使用 send() 方法发送数据alert("数据发送中...");};ws.onmessage = function (e) {console.log("接受到消息:"+e.data);createEle(e.data);};ws.onclose = function () {// 关闭 websocketalert("连接已关闭...");};function sendMsg(msg) {ws.send(msg)}</script>
<body>
<div class="wrap flex-column"><div class="box"><video src="shape.mp4" width="100%" height="100%" controls autoplay></video></div><div class="send flex-row"><input type="text" class="con" placeholder="弹幕发送[]~(^v^)~*"/><div class="send-btn" onclick="javascript:sendMsg(document.querySelector('.con').value)">发送</div></div>
</div>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script>//1.获取元素var oBox = document.querySelector('.box');   //获取.box元素var cW = oBox.offsetWidth;   //获取box的宽度var cH = oBox.offsetHeight;   //获取box的高度function createEle(txt) {//动态生成span标签var oMessage = document.createElement('span');   //创建标签oMessage.innerHTML = txt;   //接收参数txt并且生成替换内容oMessage.style.left = cW + 'px';  //初始化生成位置xoBox.appendChild(oMessage);   //把标签塞到oBox里面roll.call(oMessage, {//call改变函数内部this的指向timing: ['linear', 'ease-out'][~~(Math.random() * 2)],color: '#' + (~~(Math.random() * (1 << 24))).toString(16),top: random(0, cH),fontSize: random(16, 32)});}function roll(opt) {//弹幕滚动//如果对象中不存在timing 初始化opt.timing = opt.timing || 'linear';opt.color = opt.color || '#fff';opt.top = opt.top || 0;opt.fontSize = opt.fontSize || 16;this._left = parseInt(this.offsetLeft);   //获取当前left的值this.style.color = opt.color;   //初始化颜色this.style.top = opt.top + 'px';this.style.fontSize = opt.fontSize + 'px';this.timer = setInterval(function () {if (this._left <= 100) {clearInterval(this.timer);   //终止定时器this.parentNode.removeChild(this);return;   //终止函数}switch (opt.timing) {case 'linear':   //如果匀速this._left += -2;break;case 'ease-out':   //this._left += (0 - this._left) * .01;break;}this.style.left = this._left + 'px';}.bind(this), 1000 / 60);}function random(start, end) {//随机数封装return start + ~~(Math.random() * (end - start));}var aLi = document.querySelectorAll('li');   //10function forEach(ele, cb) {for (var i = 0, len = aLi.length; i < len; i++) {cb && cb(ele[i], i);}}forEach(aLi, function (ele, i) {ele.style.left = i * 100 + 'px';});//产生闭包var obj = {num: 1,add: function () {this.num++;   //obj.num = 2;(function () {console.log(this.num);})}};obj.add();//window</script>
</body>
</html>

这样一个实时的视频弹幕功能就完成啦,是不是很简单,各位小伙伴快来试试吧。

bbf81448dff18b6477b828ad453fa975.png

5 小结

上班撸代码,下班继续撸代码写博客,这个还是很简单,笔者写这个的时候一会儿就写完了,不过这也得益于笔者很久以前就写过netty的服务,对于Http,Tcp之类协议也比较熟悉,只有前端会有些难度,问下度娘,也很快能做完,在此分享出来与诸君分享,有问题可找笔者交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_791464.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Drupal 网站漏洞修复以及网站安全防护加固方法

drupal是目前网站系统使用较多一个开源PHP管理系统&#xff0c;架构使用的是php环境mysql数据库的环境配置&#xff0c;drupal的代码开发较为严谨&#xff0c;安全性较高&#xff0c;但是再安全的网站系统&#xff0c;也会出现网站漏洞&#xff0c;drupal是网站运行访问必不可少…

【Python爬虫系列】为什么我喜欢python?来看看这些让人爱不释手的原因吧,购物网站大盘点,看过这些python做的项目,我立马入坑了…(神奇 | 爱了,爱了)

导语 Python编程零基础如何逆袭成为爬虫实战高手&#xff1f;&#xff01; 哈喽&#xff01;我是木木子&#xff0c;你们的贴心小助手。想学习爬虫的小可爱注意啦&#xff0c;一定不要错过哦~ 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝白嫖源码福利&#x…

oss php sdk+laravel搭建图片处理静态网站

背景和目标 接着上两篇继续写oss php sdklaravel搭建静态网站。 主要说下静态网站的重要部分图片服务&#xff0c;现在很多的网站上都会用到大量的图片, 图片在网页传输中占据很大的数据量, 图片处理也是影响网站性能的重要因素。 这篇文章主要结合oss的图片处理功能介绍如何利…

学习编程有疑问?七个网站助你菜鸟变大牛

很多同学在学习编程时候会遇到各种各样的问题&#xff0c;这些问题需要自己去想办法解决&#xff0c;那么这些网站平台将会给你很大的帮助。 1、W3school 这是一个免费学习编程语言的在线学习网站&#xff0c;里面的知识浅显易懂&#xff0c;非常适合初学者。如果你对编程还不…

前端学习的几个网站

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01;1.菜鸟教程&#xff1a;http://www.runoob.c…

【云计算的1024种玩法】10分钟轻松设置出 A+ 评分的 HTTP/2 网站

前言 其实 HTTP/2 应该是 2015 年的老话题了&#xff08;2015 年 5 月 14 日 HTTP/2 协议正式版的发布&#xff09;&#xff0c;但是 2018 年都到了很多网站依旧没有使用&#xff0c;作为新一代互联网协议&#xff0c;HTTP/2 不仅速度比目前常见的 HTTP/1.1 更快&#xff0c;而…

如何优化网站,网站推广优化一般流程

理论上针对不同类型的网站&#xff0c;优化网站的策略是不完全相对&#xff0c;但基于搜索引擎网站排名的原理&#xff0c;对于任何一个网站优化流程&#xff0c;都可以参考如下方法&#xff1a; 1、网站架构设计 在做网站信息架构的时候&#xff0c;我们并不单纯的只是简单的罗…

引路蜂Android技术网站开通了

分享一下我老师大神的人工智能教程。零基础&#xff01;通俗易懂&#xff01;风趣幽默&#xff01;还带黄段子&#xff01;希望你也加入到我们人工智能的队伍中来&#xff01;https://blog.csdn.net/jiangjunshow之前在引路蜂技术博客我们花了大量的篇幅介绍了Android开发的相关…

【面试精选】关于大型网站系统架构你不得不懂的10个问题

该文已加入笔主的开源项目——JavaGuide&#xff08;一份涵盖大部分Java程序员所需要掌握的核心知识的文档类项目),地址:https://github.com/Snailclimb/JavaGuide 。觉得不错的话&#xff0c;记得点个Star。下面这些问题都是一线大厂的真实面试问题&#xff0c;不论是对你面试…

网站高并发及高并发架构详解

高并发是指在同一个时间点&#xff0c;有很多用户同时的访问URL地址&#xff0c;比如&#xff1a;淘宝的双11&#xff0c;双12&#xff0c;就会产生高并发,如贴吧的爆吧&#xff0c;就是恶意的高并发请求&#xff0c;也就是DDOS攻击&#xff0c;再屌丝点的说法就像玩撸啊撸被AD…

大型网站技术架构(二)架构模式

2019独角兽企业重金招聘Python工程师标准>>> 每一个模式描述了一个在我们周围不断重复发生的问题及该问题解决方案的核心。这样&#xff0c;你就能一次又一次地使用该方案而不必做重复工作。 所谓网站架构模式即为了解决大型网站面临的高并发访问、海量数据、高可靠…

大型网站技术架构(五)网站高可用架构

2019独角兽企业重金招聘Python工程师标准>>> 网站的可用性&#xff08;Avaliability&#xff09;描述网站可有效访问的特性。 1、网站可用性的度量与考核 网站不可用时间&#xff08;故障时间&#xff09;故障修复时间点-故障发现&#xff08;报告&#xff09;时间点…

大型网站技术架构(一)大型网站架构演化

2019独角兽企业重金招聘Python工程师标准>>> 看完了有一本书&#xff0c;就应该有所收获&#xff0c;有所总结&#xff0c;最近把《大型网站技术架构》一书给看完了&#xff0c;给人的印象实在深刻&#xff0c;再加上之前也搞过书本上讲的反向代理和负载均衡以及ses…

linux 查看机器硬件配置,在linux下如何查看机器硬件配置?_网站服务器运行维护...

在windows中用鼠标选定多个不连续文件的操作是什么_网站服务器运行维护在windows中用鼠标选定多个不连续文件的操作是&#xff1a;首先打开需要选定的文件&#xff1b;然后按住【Ctril】键不放&#xff0c;单击需要的文件&#xff1b;最后出现选中状态即可。在linux下如何查看机…

开源网站分析软件Piwik的数据库表结构

文章引用&#xff1a;【http://www.biaodianfu.com/piwik-database-schema.html】 Piwik是一套基于PhpMySQL技术构建&#xff0c;能够与Google Analytics相媲美的开源网站访问统计系统&#xff0c;前身是phpMyVisites。Piwik可以给你详细的统计信息&#xff0c;比如网页浏览人…

使用最新 solr4.10 快速开发团购网站等垂直搜索网站

说明&#xff1a; solr 是一个非常完善的开源项目&#xff0c;非常优秀&#xff0c;他不紧紧是做个索引这么简单&#xff0c;而是可以做成一个垂直的网站&#xff0c;比如团购网站&#xff0c;快速搭建页面。而且solr带了一个非常优秀的管理后台。可以查看管理&#xff0c;导入…

发现一个国外的学习网站

一个国外的学习网站 udacity.com 优达学成。 免费课程 https://cn.udacity.com/courses/all 全部的课程 里面有不少有意思的课程。 课程是英文的带中文翻译。 还有一个机器学习的课程&#xff0c;感觉好高大上啊。 总结 使用上有点不太方便。 本地化做的还不是很…

javascript ,从mozilla 官方网站学习语法,非常不错

本文的原文连接是: https://blog.csdn.net/freewebsys/article/details/81153733 博主地址是&#xff1a;http://blog.csdn.net/freewebsys 1&#xff0c;关于mozilla 开发者 https://developer.mozilla.org/zh-CN/ 还有这么一个开发者中心呢&#xff0c;上面搜索写JavaScri…

pagespeed insights 上线了,可以通过web进行网站性能分析了

地址&#xff1a; https://developers.google.cn/speed/pagespeed/insights/ 分析下csdn网站&#xff1a; 功能挺多的&#xff0c;还不错。 可以进行参考&#xff0c;然后优化。提高访问速度。

中国大学MOOC(慕课) 一个不错的学习网站

https://www.icourse163.org/category/all 中国大学MOOC是由网易与高教社携手推出的在线教育平台&#xff0c;承接教育部国家精品开放课程任务&#xff0c;向大众提供中国知名高校的MOOC课程。在这里&#xff0c;每一个有意愿提升自己的人都可以免费获得更优质的高等教育。 央…