编译出错: /opt/ros/kinetic/include/moveit/macros/declare_ptr.h:52:16: error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
解决方法: 取消CMakeLists.txt下 add_compoile_options( -std=c++11 ) 的注释 原因: ROS都是按照c++03的编译方法进行,如果使用了新标准c++11,则需要先这么处理一下,告知用c++11的方式进行编译。
参考: https://blog.csdn.net/gyzgyz1989/article/details/53207192 https://answers.ros.org/question/216842/ros-using-c-11-how-to-use-with-catkin/
本文作者Easy,程序员中的网红
如果你是一个混迹微博的IT爱好者的话,可能对下面这个头像有印象。
没错,这就是Easy!
从2003年写下第一行PHP代码开始,编程就成为了他生活的日常。而他的人生履历,也与编程紧密切合。
2004年,他入职新浪,负责WAP发布平台,日访问量2亿;
后来,他成为了新浪云资深产品架构师,平台访问量8亿+;
Easy出版的《程序员跳槽全攻略》,为程序员跳槽提供了方法论和工具,全网累计分发量超过8万;
现在,他是一位独立开发者,同时也为想要入行编程的小伙伴提供帮助。
接下来,让我们看看今天Easy到底想分享给我们什么方法来学习编程呢?
01
自从业以来,我就不停地被问到类似「编程到底难不难呀,我能不能学会呀?」这样的问题。
要是以前你问我这个问题,我肯定会回答,一点都不难。你如果去问十年以上的老程序员们,估计答案都差不多。
但是去年我开始系统化的梳理 Web 全栈相关的知识点以后,发现现在学习编程,和我们那个年代学习编程,已经完全不一样了。
以 Web 为例来说明吧。
作为和互联网一起成长起来的一批程序员,我们最开始接触的 Web 是非常简单的,最开始只有HTML 、然后才有了 CSS 、再之后 Ajax 才兴起。
我们都是先学会了核心,再一点一点的去学新增的内容,所以我们一点都不觉得难。
但今天,用户对网页的要求越来越高,整个 Web 开发的知识累积量也已经非常庞大。
众多陌生的知识一拥而上,很容易让人不知所措,甚至心生恐惧。想想以前我们用一个长假可以把 HTML 学一遍,还能做几个小表单;
现在可能连 WebPack 语法都还没看完,这要何时才是个头呢。
所以我觉得,如果方法不对的话,编程可能是挺难的。
02
那么什么样的方法才是管用呢?
先来听我讲讲一个朋友的故事。在那个国庆节之前,编程曾经是他认为不可能学会的事,而在那个国庆节之后,编程成为了他最擅长的事。
严格的说呢,这位朋友并不算一个好学生。进入大学后便迷上了CS,大三因为挂科太多被学校劝退了。
这下他清醒了,这样下去不行,但学校已经回不去了,于是报了个培训班学编程求生。
天天学天天练,学了三个月,但都没入门。也不是不会,是只有老师教过的才会,和教的只要一点不一样,就立马不会了。
不久后,他在火车上遇到一位大厂的程序员,闲着没事,两人就一起聊编程。聊了不到一个小时,就豁然开朗了。
我问他怎么就开朗了,能不能说具体点,他说,原来脑子里虽然装满了知识,但也就是那么放在那里,每个知识都一样。
但当明白了 Web 开发到底是在做什么以后,这些知识就有了权重、有了优先级、有了结构和位置。
脑子就像有一根绳,将这些知识分门别类的串了起来。哪些知识干什么用,变得清清楚楚。
把那些周边知识先扔一边,重点攻克那些主干知识,就能从中杀出一条血路来,等主干知识巩固好了,再慢慢回来补周边知识。
仔细想想,我其实也在无意间使用着这种学习方法,于是后来在其基础上进行了强化,用到公司的新人培训上,效果甚好,这里分享给大家。
03
我叫它「多周目知识树学习法」。
分开来讲。
先说多周目,周目就是轮次的意思,经常玩游戏的同学应该会知道,很多剧情都要二周目甚至三周目才能玩出来。这里借用的就是这个概念。
作为初学者,我们不奢求一次吃个胖子,我们分多次来学习。
第一遍看全局,知道有哪些东西,每一部分都是干什么用的,哪些重要,哪些不重要。
第二遍重原理,从最核心的原理出发,一步一步尝试以最短的路径走通整个流程,完成核心任务。
第三遍补周边,把之前做的方案拿出来,看看哪些地方可以优化,哪些地方能做得更好。
这么几遍下来,每次的学习难度降低了不少,而我们对知识的理解却深入了很多。
然后是知识树。
就像前文所说,知识点并不是平等的。我们需要在理解本质和原理的基础上,梳理出一颗知识树。
在这棵树上,我们应该可以清晰的看到哪些知识是核心、那些知识是周边,我们为什么要学它、学了它能用到那些地方。
每个人的知识树可能不一样,会随着你的理解进行调整。初学者往往很难立马建立起来完整的知识树,这时候可以借助一些学习路线图作为样本。
如果你正在或者想要学习的是PHP和Web开发,那么我这里正有一份之前梳理课程时做的、有几百个细节知识点的学习路线图可以免费下载。
(拉到文末扫码进群,即可获取高清图表)
学好编程并以此为职业并不是一件容易的事情,这里也只是针对我们发现的问题提出的方法,希望能对在学习摸索中的你有所帮助。
我与网易云课堂合作出品的《全栈开发工程师5天实战营》,将会通过5天时间,以《动图小工厂》实战课程为案例,除了视频学习资料外,还有讲师、助教互动答疑,组队对抗惰性,与小伙伴共同进步。
原价99元,限时免费学
先说结论,这种用法的目的是为了防止重复定义,而不是所谓的重复声明。
其实这一点也是很容易理解的,头文件的定义本身就是为了引入“声明”的,如果不允许重复声明,那多个文件引用同一个头文件就非法了,这显然是错误的,在C编译中,恰恰是允许也需要重复声明的,只要引用声明了,就可以远程使用该声明对应的对象(变量或函数)。
假设:
#ifndef xxx #define xxx unsigned char a[]={..........}; ............ #endif 这里,在头文件中出现了变量定义,这种情况下,这个#ifndef才有了作用,第一次被引用时,该定义能够同时被包含,但是第二次,由于已经define xxx了,所以这个定义就不能被重复包含了,这样就能有效的避免重复定义而报错了,因为编译过程中,声明可以,但是重复定义是不可以的。
| 导语 外部存储作为开发中经常接触的一个重要系统组成,在Android历代版本中,有过许许多多重要的变更。我也曾疑惑过,为什么一个简简单单外部存储,会存在存在这么多奇奇怪怪的路径:/sdcard、/mnt/sdacrd、/storage/extSdCard、/mnt/shell/emulated/0、/storage/emulated/0、/mnt/shell/runtime/default/emulated/0…其实,这背后代表了一项项技术的成熟与发布:模拟外部存储、多用户、运行时权限…
一、各版本外部存储特性 Android 4.0
支持模拟外部存储(通过FUSE实现)
出现了主外部存储,以及二级外部存储(没有接口对外暴露)
支持MTP(Media Transfer Protocol)、PTP协议(Picture Transfer Protocol)
Android 4.1
开发者选项出现”强制应用声明读权限才可以进行读操作”的开关
Android 4.2
支持多用户,每个用户拥有独立的外部存储
Android 4.4
读操作需要声明READ_EXTERNAL_STORAGE权限
应用读写在外部存储的应用目录(/sdcard/Android/
/)不需要声明权限
增加了Context.getExternalFilesDirs() 接口,可以获取应用在主外部存储和其他二级外部存储下的files路径
引入存储访问框架(SAF,Storage Access Framework)
Android 6.0
外部存储支持动态权限管理
Adoptable Storage特性
Android 7.0
引入作用域目录访问
补充一个点:如果应用的minSdkVersion和targetSdkVersion设置成<=3,系统会默认授予READ_EXTERNAL_STORAGE权限
二、部分特性讲解 1. 模拟外部存储 a. 必要性
FAT32 属于微软专利,可能存在许可和法律问题(相关文章(https://www.howtogeek.com/183766/why-microsoft-makes-5-to-15-from-every-android-device-sold/));
可以定制Android自己的外部存储访问规则;
为多用户做铺垫;
b. 实现原理
系统/system/bin/sdcard守护进程,使用FUSE实现类FAT格式SD卡文件系统的模拟,也就是我们经常说的内置SD卡。(详细代码可以参考:/xref/system/core/sdcard/sdcard.c)
用户空间文件系统(Filesystem in Userspace,简称FUSE)是一个面向类Unix计算机操作系统的软件接口,它使无特权的用户能够无需编辑内核代码而创建自己的文件系统。目前Linux通过内核模块对此进行支持。
sdcard守护进程模拟外部存储大致流程(Android 4.0为例):
首先,指定/data/media目录用于模拟外部存储。该路径的owner和group一般为media_rw,这样保证只有sdcard程序或root进程能够访问该目录。
# create virtual SD card at /mnt/sdcard, based on the /data/media directory # daemon will drop to user/group system/media_rw after initializing # underlying files in /data/media will be created with user and group media_rw (1023)service sdcard /system/bin/sdcard /data/media 1023 1023 class late_start
1、下载 Qt5 离线安装包
下载地址:http://www.qt.io/download-open-source/ 进入后,请注意页面最下方有个【View All Downloads】链接,点击它可找到离线安装包! 根据自己的操作系统版本,选择对应的安装包: 2、添加执行权限
下载完成后,得到离线安装包,打开【终端】,进入离线安装包所在的目录,然后执行命令:
sudo chmod +x qt-opensource-linux-x86-5.4.1.run 1 3、开始安装
添加执行权限后,可以开始安装Qt5,在步骤2的基础上,继续运行命令:
sudo ./qt-opensource-linux-x86-5.4.1.run 1 可见如下窗口: 接下来按照编号指示的步骤依次操作: 4、配置环境变量
在【终端】中执行如下命令:
sudo gedit /etc/profile 1 添加如下内容: 32位系统:
export QTDIR=/opt/Qt5.4.1/5.4 export PATH=$QTDIR/gcc/bin:$PATH export LD_LIBRARY_PATH=$QTDIR/gcc/lib:$LD_LIBRARY_PATH 123 64位系统:
export QTDIR=/opt/Qt5.4.1/5.4 export PATH=$QTDIR/gcc_64/bin:$PATH export LD_LIBRARY_PATH=$QTDIR/gcc_64/lib:$LD_LIBRARY_PATH 123 上面的路径,请自己对照所安装的版本更改!
保存退出, 执行命令:source /etc/profile 让环境变量生效!
5、验证是否安装成功
终端下执行命令:qmake -version
如果出现如下信息,表示配置安装成功:
6、测试实例
打开Qt Creator,点击New Project,创建一个新项目:
7、解决错误
当尝试运行时,会有错误出现:
根据错误提示,我们打开如下的界面:
出现上述错误是因为我们没有安装可用的g++编译器(基本上所有的linux发行版都自带安装了gcc编译器),在终端中执行如下命令:
sudo apt-get install g++ 1 安装完成后,重新打开Qt Creator,可以发现已经找到编译器了:
遥感的通用格式为tiff格式 【科普】无人机遥感技术的几个领域应用 2016-09-14 10:10 来源:无人机频道 无人机 /科普 原标题:【科普】无人机遥感技术的几个领域应用
无人机遥感在气象监测中的应用
无人气象飞机可装载遥感设备对温度、湿度、压强等气象参数进行遥感测定, 而且这方面的研究取 得了一定的成果。美国在20世纪60年代就开始采用名为Com pass Cope 的遥控飞行器(RPV)即无人机代替气象飞机 WC -130 作为空中气象侦查平台通过 1970 年到 1974 年 5 年的飞行试验,认为无人机有诸多优点可以代替气象卫星。
在世界气象组织(WMO)大气探测委员会和国际科学联盟理事会支持下,国外提出了微型无人驾驶探空飞机发展计划。中国气象局也将微型无人驾驶飞机探空的研究工作列入“八五”计划。马舒庆等用GPS导航无人机携带数字电子探空仪在河北省怀来县和南昌北郊南昌新机场两地进行了1000m 和 3000m 的高度探测试验,并将风速测量结果与探空站雷达测得的结果进行比较和两种测量技术所得的结果非常 接近,且温度、气压、湿度和测量精度也都达到设计指标。
沈怀荣等利用微小型无人机探测气象参数,该方法可以在空中长时间、大区域连续监测天气变化得到高精度测量结果。
无人机遥感在资源调查与监测中应用
无人机遥感在资源调查与监测方面的应用主要是土地、资源调查与分类,环境监测等。
广西气象减灾研究所的马轮基等2002年利用装载佳能EOS 300D型数码照相机的无人机对广西武鸣县进行土地资源调查 ,得到的武鸣县城区域土地利用遥感图。经实地取样测量检验定位平均偏差 1 m ,最大偏差 2 m ,水平方向上长度变形小于 1 %, 基本没有角度变形 。
2003 年中国测绘科学研究 院研制完成的 UAVRS — Ⅱ型低空无人机遥感监测系统选用高分辨率面阵 CCD 数码相机作为主要遥感设备 ,实现了大比例尺航摄的面积覆盖 ,并通过国土资源部组织的部级验收。谢彩香等根据中药资源分布特点利用无人机进行抽样调查 , 结合航天遥感计算中药资源的总量, 大大节省了成本,并使其结果具有统计学的可靠性。
台湾大学理学院空间信息研究中心利用无人机拍摄低空大比例尺图像 ,配合 FORM OSA T2 分类进行异常提取, 解译桃园县非法废弃堆积物(固体垃圾等), 用于环境污染和执法调查。朱子豪等 2004 年使用无人机携带大面阵数码相机在台湾盐寮福隆海岸进行追踪调查, 对沿岸环境、土地、厂房、污染等进行了监测。
本文来自陌陌视频流媒体技术负责人吴涛在WebRTCon 2018上的分享,他详解了陌陌从传统直播过渡到1对1到多人互动模式的演进,架构的优化保证了用户体验与业务需求。另外,文末为WebRTCon 2018最后一波PPT分享,点击阅读原文下载。
文 / 吴涛
整理 / LiveVideoStack
概览
我有幸曾在互联网、安防监控、广电音视频传输三大领域从事工作,感觉自己现在的水平应该仅够满足实战需求了,所以今天在这里不敢说为大家做分享,只能说为大家汇报一些自己在这三个领域工作的心得体会。
互联网直播的话题已经是老生常谈了,我们也很难再讲出来一些新的东西。我最早来到陌陌的时候,陌陌做音视频传输技术的只有四个人,一个做客户端,一个做支付,一个做后台,剩下一个由我来做音视频。可以说我见证了陌陌直播从襁褓之中成长为现在这样一个成熟直播平台的全过程。2017年Q4财报显示,陌陌现在月活跃用户数9910万人,收入是3.58亿美元,而陌陌视频收入约3.2亿美元,也就是说陌陌90%多的收入都是视频提供的,这是现在陌陌直播平台的发展情况。
今天我向大家分享的主要内容有:
基于CDN架构的直播应用
基于CDN架构的低延迟直播的应用
CDN架构下非交互直播的问题
带有交互能力的直播
直播技术未来的发展
1.基于CDN架构的直播应用
这张图是陌陌APP直播界面去除礼物、动画等元素的效果图。一位主播在屏幕前为用户表演。主播能做的事,对着屏幕表演,用户除了给主播送礼物或发消息外无法与主播进行其他交互。有时用户会发现主播不会对自己发送的消息作出反馈,这是为什么?第一种原因可能是这位主播受关注度比较高,消息量比较大,无法一一进行回复;第二种原因可能是此时端对端延迟过大,使得主播响应无法及时送达到观众端。
以上是其中一种基于CDN架构的直播架构图。这个架构图很简单,主播把直播数据推到了一个CDN的边缘节点,用户再从CDN的另一端的边缘节点获取直播数据,这种架构在直播当中十分常见,为什么使用这种简单架构?
1.1优势
显而易见的是,其优势就是简单。使用这种架构意味着企业不需要开发者有多强的网络技术能力,只需要确定域名后把音视频传入即可完成。并且,简单意味着这种架构的开发效率非常高,也许只需编写几行代码或者进行配置即可完成。对于一个应用型公司来讲,这种方案的开发门槛很低,所需要的时间、人力资源成本都很低,这也是互联网直播使用CDN的好处之一。
1.2 劣势
当然这种方案也存在劣势。第一我们知道CDN是建立在TCP协议上的,这就导致CDN会受到TCP协议本身的约束,实时音视频数据传输TCP协议栈并不十分理想;第二是使用CDN质量差异较大;第三是使用CDN难以随需求进行定制化,CDN面对很多用户的需求都是非定制化的;第四是使用CDN架构端对端的延迟大,我特意使用虚线将主播与观众相连标记时间。虽然每家公司的CDN解决方案都号称端对端延迟只有三秒,实际上如果从用户良好体验的角度出发,经过测算端对端的延迟控制在5秒比较理想,低于5秒就可能会出现卡顿等影响体验的问题。
1.3 技术关键点
CDN架构是直播的基础方案,我们必须把这个方案做得足够完美才能在直播体验上有优势。除了以上叙述的关键点,在实际应用场景上CDN还会受到很多条件的约束:从用户体验的角度来讲,观众使用手机观看直播,无论是使用陌陌还是其他友商的APP,当使用这个应用进入感兴趣的直播间首先体验到的是能够快速呈现直播内容。如果用户点击某个直播间后需要等待一下或者获取视频失败,无疑是一个非常糟糕的体验;其次是画面的清晰度与流畅程度;再次是与主播间的延迟这些都是从用户体验的角度出发遇到的问题,我们需要使用技术手段来解决用户遇到的这些问题。
我们把遇到的这些问题大致分成两个方面并加以解决:一个是传输的前端,一个是传输的后端。
1.3.1 传输前端·推流器问题
首先需要解决的是传输的前端也就是主播端,在主播端需要解决的是推流器问题。
1)抗拥塞
对用户而言在直播体验上最糟糕的无疑是卡顿。用户希望能够看到流畅的直播,但是如果使用TCP协议就会出现拥塞问题,那么我们如何来抗拥塞呢?抗拥塞本质是是降低TCP协议拥塞构成的干扰,其原理比较简单,一种方案是减少在推流器上发送的数据,降低帧率、码率、分辨率等各种数据的传输量,数据的传输效率降低,拥塞对直播画面的影响就会减弱;另一种方案则更加简单粗暴,也就是一旦出现拥塞我们就丢弃数据或者重新建立链接,这样也会有效减弱拥塞对直播画面的影响。
2)秒开问题
第二点就是秒开问题,也许会有人认为使用CDN架构并不存在秒开问题,只要缓冲第一帧是关键帧就可解决。这个观点没错但是不全面,需要缓冲多少数据?是缓冲一个关键帧还是关键帧所在的一个完整的GOP?还是一个关键帧与一些P帧(对于直播而言很少有B帧,因为B帧的编解码耗时多,所以直播视频尽量不使用B帧)?具体缓冲多少?这便牵扯到如何对GOP进行设置,而GOP的设置必须由编码器决定,因为对于直播视频流而言,一个GOP中I帧的占比是非常大的,与同等参数下的体育直播不一样。体育直播P帧与I帧的大小实际上是近似的,因为体育直播受到场景画面变化剧烈的影响,也就是说GOP的具体参数需要根据直播场景与视频画面进行设置,并不能简单理解为在CDN边缘只缓存一个关键帧或者只缓存几个数据就能解决。也许一个GOP值设置的非常庞大导致一个GOP需要三秒钟,当用户打开直播画面时一个关键帧后画面出现一个跳转,这种的体验是非常糟糕的。我们根据直播的场景在编码器上设置GOP能够妥善处理秒开问题。
3)清晰度
用户需要能够快速打开视频并且流畅观看,也需要看到清晰的画面。以家庭影院为例,从最早的录像带,进化成VCD再进化到DVD,再进化到现在的蓝光4K等等,画面清晰度始终是用户所追求的一项重要指标。这里我有一份数据统计:陌陌在每年1月7号都会有一个盛典,直播舞台上进行的一些表演。我把直播画面清晰度进行了简单分类,第一个是960×540的标清分辨率,第二个是1280×720的高清分辨率,第三个是1080P的全高清分辨率。分辨率为960×540时传输需要1M的带宽,这时如果通过正常的互联网传输直播画面是很少卡顿的;而当分辨率提高到1280×720时就需要2.5M到3M左右的带宽进行传输,这时如果用户是在家里拿手机看直播画面便会出现一些卡顿;当分辨率提高到1080P时稳定传输需要5M以上带宽,在这种情况下除非用户家里宽带的网络质量非常好或者手机4G信号特别强,否则就会出现多次直播画面的卡顿。但根据用户反馈的数据来看:分辨率为720P的观看用户是最多的,使用1080P观看直播画面的用户占到了总用户量的10%,其中观看画面模糊但流畅的用户只占不到25%,也就是说清晰度对于用户而言非常重要。如何在推流器端优化清晰度呢?解决此问题不只依赖某个技术点,我们可以通过场景渲染、色彩增强等技术,也可根据直播环境背景色调整主播的着装、环境光照等等,这些都会决定画面的清晰度;我们可以将一路画面设置成不同的分辨率,对于两个不同的分辨率的视频我们可以使用光照去弥补,使得用户在不同的分辨率上看到近似清晰的效果。总而言之,我们可以对不同的场景进行调整与匹配,优化画面的清晰度。
1.3.2 传输后端·播放器问题
解决完推流器问题,接下来需要解决的是播放器问题。
1)抗卡顿
关于播放器首先需要解决的还是卡顿问题。抗卡顿是保证用户体验中最重要的方面,尤其是对于直播而言。那么如何在播放器端妥善解决卡顿问题?较为简单的方案是加缓冲,缓冲区的存在可以有效减少卡顿的次数与机率。
2)抗延迟
为什么用户给主播发消息给主播,隔了好厂一段时间才有反馈?因为直播画面存在延迟。卡顿与延迟是互相矛盾的条件,画面流畅意味着可能延迟增大,延迟减小画面又可能会因为网络不稳定等原因出现卡顿。关于这一点我们只能针对不同使用场景和业务环境进行动态调整,在减少延迟的同时尽量保证画面的流畅。
3)拉流成功率
关于这一点的问题比较少见,理论上CDN模式能够全球覆盖、全网覆盖,拉流肯定会成功,实际并非如此。举个极端的例子,西部偏远地区会经常出现拉流失败;而在在流量高峰时段,数据采集拉流成功率只有90%左右,这就会导致用户无法成功打开直播画面,直播清晰度流畅度也无从谈起了,所以拉流成功率也需要我们关注。关于拉流成功率还需要说明的一点是,因为一些规模较小的宽带运营商会做一些网带缓冲,也可以说是域名劫持。一旦出现域名劫持自然无法成功拉流或者拉到非线上直播的流,这比较麻烦。为解决这一问题,在陌陌我们可能不一定下发IP而是一个302的调度点。通过这些措施来保证客户端成功获取正确的视频流,确保拉流成功率。
2.基于CDN架构的低延迟直播的应用
讲完了CDN架构的简单应用,接下来讲一讲年初最火的直播答题。这张图是陌陌的一个直播答题界面,直播答题实际上有什么难点呢?
3.CDN架构下非交互直播的问题
延迟高、交互性差、表演内容相似度高、观众无法简单参与
为什么会有这些问题?因为此方案只是把播放器和CDN上的边缘缓冲全部去除,这种模式是最简单的。我们没有对现有的CDN架构进行重大调整而是将主播推到CDN变成将主播推到三体云,只需要调整SDK上的几行代码即可实现。
4.带有交互能力的直播
模式一:普通连线
虽然普通连线解决了最简单的问题,但在实际应用场景中基本已经没有厂商使用这种模式,因为通过这种模式达成的直播效果十分单调。
模式二:主播间连线
主播与主播之间的连线实际上是现在最受直播平台与主播欢迎的一种直播答题模式。对于平台而言可以通过这种模式让一些不知名的主播与知名主播进行PK,能够为提升主播知名度同时给直播平台带来流量;对于主播而言通过与别的主播进行PK可以推出新玩法,进一步的互动避免直播内容的同质化。这种模式的架构是数据从两位主播所在的手机编码器两端推到CDN,观众从CDN边缘获取直播数据;与此同时数据也由主播端推到中间的互动云服务器,主播与主播之间通过互动云进行连接。这种架构是最初搭建的一种,因为简单到不需要大的改动就能实现。但实际上这种架构也存在问题:也就是这需要双推主播端的直播数据,一路数据被推到CDN一路数据推到互动云。两路数据意味着两路编码,这对CPU、对带宽的消耗很大。根据简单测试在正常的环境或者在Wi-Fi的环境下,手机推流超过1.2M的时出现抖动的机率就会显著提高。两路编码会带来较高的CPU性能损耗,进而导致手机的发热问题。如果我们对这种架构进行优化:
采用单推也就是把两个主播端的数据先推到互动云,数据在互动云进行混合转码后推到CDN边缘结点,这样在主播的编码器端只有一路数据需要推至云,剩下处理过程的由服务器代劳,便可解决双推带来的问题。 模式三:多人连线(狼人杀模式)
第三种模式是多人联线,我们内部称其为“狼人杀模式”。为什么叫狼人杀模式?多人连线这个模式其实是由“狼人杀”演变而来的。最早我们只是考虑观众和主播或主播和主播互动,从来没考虑到观众之间也能实现互动。其实我们发现普通人有时更想参与互动,但是面对主播又无法去有效表达,远没有观众之间互动的参与热情高。这种模式也非常受平台青睐,因为在这种模式下用户停留的时间就会变长。让用户以较低成本参与其中,不需要用户具有特别的才艺就能展现自我。这也使得直播软件成为一种社交方式,一个全民级应用。这种架构相对之前的更为简单,也就是将所有参与用户的音视频数据传到互动云上就行了;互动云再将数据推给CDN,对于不想看或者不想参与的用户可以从CDN拉流,对于想观看或者想参与的用户可以连接到互动云。当然这种模式也存在问题:我们知道普通人面对镜头的压力还是非常大的,就像美颜、滤镜是现在自拍的标配一样,在直播中露脸这件事对普通用户而言往往带来较大压力。
模式四:电台模式
模式三的问题使其演变成了第四种模式——电台模式,也就是只直播用户的音频,这样虽然不存在画面但是业务模式并未改变。在这里我有一个问题:模式四能否直接套用模式三的架构?其实模式四用模式三是不行的,因为在实时互动云模式下,主播之间的延迟是不足1秒的,但主播与观众之间的延迟是5秒左右。对于视频画面我们可以用转场动画处理使用户不易察觉到这5秒延迟的存在,而在纯音频模式下无法用这种措施进行处理优化,因为用户听到的音频是连续的,一旦少了一部分就会使用户体验大打折扣。所以对于第四种模式我们使用更加简单的方式处理,也就是不经过CDN而直接用互动云处理数据。用户如果想参与直播互动就打开麦克风,如果只想听直播就关闭麦克风。对我们而言这种全新模式能够以更低的开发成本为用户带来更好的交互直播体验。
互联网直播是否能改变直播行业?既然互联网直播能够实现互动,那么电视直播能否实现互动?当然我们无法在家看电视直播时通过APP和电视台主持人聊天。第一是因为电视直播从采集到播出需要层层的安全审核。第二是因为缺乏更先进的数据传输技术,现有技术无法将电视直播的数据高效传输至互动云。关于这一点在陌陌6月推出的世界杯直播业务时已经可以实现互动直播,也就是在世界杯现场用摄像机,导播台,编码器等一系列硬件设备搭建起一个直播环境。用户通过APP就能在观看直播时和主持人互动,为什么说这和电视直播的不一样?因为在传统演播室环境下,电视台对直播的安全与稳定性要求很高;但对于各互联网直播平台,虽然应用做得都很稳定,但在极端情况下也会有直播异常甚至崩溃的情况发生,这对于电视台而言是无法想象的直播事故。大家可以想象如果《新闻联播》在直播时出现花屏绿屏卡顿等问题会造成多么重大的影响。而对于陌陌来说,陌陌现场就是陌陌的《新闻联播》,我们需要保证不会出现任何直播事故。对此我们会使用一些传统广电的解决方案,例如所有的直播信号都是多路信号,从来不会出现一路信号异常影响整场直播的问题。那么我们如何在如此严苛条件下实现这种互动直播呢?其实做法很简单,也就是在多分路的前提下引入OBS这样一个开源的编码环境。我们在其中集成了OBS的互动SDK,也就是硬件编码器推一路信号给陌陌原站的同时OBS也推一路信号给陌陌的原站。当然这两路流在原站会区分优先级,如果原站只收到编码器推出的一路信号,那么把数据转出推给CDN,用户就可以收看到直播画面;如果原站收到OBS推出的一路信号,便会将来自OBS的数据流直接传输至内存里并通过信道传输出去,而编码器的流只会被挂起,当OBS出现稳定性故障时,编码器的流便会恢复,此时用户可能感觉画面变成连屏、混屏。同时在OBS上也可实现最常见的PC端连麦,以上就是在演播间如何进行互动直播的全新应用。
5.直播技术未来的发展
5.1 低卡顿
为什么说是“低卡顿”而不是说“无卡顿”?因为现有的技术还无法实现完全没有卡顿、缓冲。这不单单取决于技术,更包括基础设施的建设,我们只是希望把卡顿率降到最低。根据陌陌的PV统计数据,用户每观看15分钟以上直播必然会出现一次卡顿,这个值是根据数据收集而并非理论计算。我们也是不断尝试尽可能优化,但实际上现在业内没有彻底解决卡顿问题的有效方案。
5.2 低延迟
CAD图纸加密后整体为一个块,无法炸开。
工具/原料
天正软件、CAD
加密图纸
方法/步骤
1、因为这里用的是天正的图纸,故先用天正电气打开加密图纸。可以看到整个图纸内容都成了一个块,点击图块跳出输入密码的框。没有密码,怎么办?
暂时关闭图纸。重新打开图纸,要注意的是,这里要通过文件-图形实用工具-修复 打开,系统进行自动检查修复。
接着打开 工具- 块编辑器,在已创建的块里面找到名为 TCH_PR 的块。
点击打开名为 TCH_PR 的块,进入块编辑器。在这里可以对这个块进行编辑。对该块里面的图进行复制,然后关闭块编辑器。
回到图纸界面,Ctrl+V 将刚才复制的内容粘帖出来。此时可以发现,复制出来的图已经破解了密码,是可以进行编辑的。
.net reactor的使用 .NET Reactor 是一款强大的 .NET 代码混淆加密保护工具,常用于防止对 .NET 程序的反编译破解等场景。
本文以.net reactor加密dll为示例:
1.新建一个类库项目,并创建一个类,本文以对称加密算法为示例 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace PP.Encrypt { //密码生成:https://suijimimashengcheng.51240.com/ public class SymmetricMethod { private SymmetricAlgorithm mobjCryptoService; private string Key; /// <summary> /// 对称加密类的构造函数 /// </summary> public SymmetricMethod() { mobjCryptoService = new RijndaelManaged(); Key = "FefZ$@pAedzg#HjT!QcM7JQqwOcAkCm7x2pZjBUMSocM9v6#%AP9HZg7OZ^ogG!x"; } /// <summary> /// 获得密钥 /// </summary> /// <returns>密钥</returns> private byte[] GetLegalKey() { string sTemp = Key; mobjCryptoService.
本来没有想到这两者之间还有什么区别,最近在项目组中就遇到了这样的问题,因此深入研究了一下。
一、以下是我对Java Web项目和Java项目这两者的理解以及区别:
1.Java Web项目是基于Java EE类的;而Java项目是基于Java应用程序的。
2.Java Web项目是网页的编码,像jsp,servlet,struts这类的,而java项目是AWT,SWING这类的编码。
3.Java Web项目中的JAVA文件是tomcat服务器来触发的,而java项目是由Main()方法来开始的。
4.Java Web项目需要服务器;而Java项目不需要服务器。
5.在Eclipse中Java Web项目可以转换为Java项目,进而可以转回到Java Web项目,如下图是具体操作步骤:
二、Java Web项目和Java项目的联系:
JavaWeb项目需要用Java来实现网站或系统的业务逻辑。
以上是我潜在的理解,大家还有什么理解或者想法,可以互相学习哦!
一说到LOD100、200、300.....很多业内人士就知道说的是模型精度,但是对于刚刚入着圈的新人来说却是个陌生的概念。今天中国BIM培训网的小编就发一篇扫盲贴,跟新人说一下什么是BIM模型精度。
模型的细致程度,英文称作Level of Details,也叫作Level of Development。描述了一个BIM模型构件单元从最低级的近似概念化的程度发展到最高级的演示级精度的步骤。美国建筑师协会(AIA)为了规范BIM参与各方及项目各阶段的界限,在其2008年的文档E202中定义了LOD的概念。 LOD被定义为5个等级,从概念设计到竣工设计,已经足够来定义整个模型过程。但是,为了给未来可能会插入等级预留空间,定义LOD为100到500。具体的等级如下: 模型的细致程度,定义如下: 100. Conceptual概念化 200.Approximate geometry 近似构件(方案及扩初) 300.Precise geometry 精确构件(施工图及深化施工图)
400.Fabrication 加工 500.As-built 竣工 LOD100 – 等同于概念设计,此阶段的模型通常为表现建筑整体类型分析的建筑体量,分析包括体积,建筑朝向,每平方造价等等。 LOD200 – 等同于方案设计或扩初设计,此阶段的模型包含普遍性系统包括大致的数量,大小,形状,位置以及方向。LOD 200模型通常用于系统分析以及一般性表现目的。
LOD300 – 模型单元等同于传统施工图和深化施工图层次。此模型已经能很好地用于成本估算以及施工协调包括碰撞检查,施工进度计划以及可视化。 LOD 300模型应当包括业主在BIM提交标准里规定的构件属性和参数等信息。 LOD400 – 此阶段的模型被认为可以用于模型单元的加工和安装。此模型更多的被专门的承包商和制造商用于加工和制造项目的构件包括水电暖系统。 LOD500 – 最终阶段的模型表现的项目竣工的情形。模型将作为中心数据库整合到建筑运营和维护系统中去。LOD 500模型将包含业主BIM提交说明里制定的完整的构件参数和属性。 在BIM实际应用中,我们的首要任务就是根据项目的不同阶段以及项目的具体目的来确定LOD的等级,根据不同等级所概括的模型精度要求来确定建模精度。可以说,LOD在做到了让BIM应用有据可循。当然,在实际应用中,根据项目具体目的的不同,LOD也不用生搬硬套,适当的调整也是无可厚非的。
原理】配置http的响应头信息:属性名X-Frame-Options。
可以配置的参数有两个:
X-Frame-Options 响应头有三个可选的值:
DENY:页面不能被嵌入到任何iframe或frame中;
SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中;
ALLOW-FROM:页面允许frame或frame加载。
在服务端设置的方式如下:
Java代码:
response.addHeader("x-frame-options","SAMEORIGIN");
Nginx配置:
add_header X-Frame-Options SAMEORIGIN
Apache配置:
Header always append X-Frame-Options SAMEORIGIN
一般选第二个参数就可以了。
【步骤】
1.在src目录下建一个包,命名为filter。在包里建类名为FrameTao。内容如下:
[java] view plain copy package filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FrameTao implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { //必须 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; //实际设置 response.
原文链接:https://blog.csdn.net/fireroll/article/details/8651593
函数名:sleep
头文件:#include<windows.h> //在VC中使用带上头文件
#include<unistd.h> //在gcc编译器中,使用的头文件因gcc版本的不同而不同
功能:执行挂起指定的描述
语法:unsigned sleep(unsigned seconds);
#include<windows.h> #include<stdio.h> int main() { int a; a=1; printf("hello"); sleep(a); printf("world"); return 0; } 函数名:usleep
头文件:#include<unistd.h>
功能:usleep功能把进程挂起一段时间,单位是微秒(百万分之一秒);
语法:void usleep(int micro_seconds);
内容说明:本函数可暂时使程序停止执行。参数micro_seconds为要暂停的微秒数*(us);
注意:
这个函数不能工作在windows操作系统中。用在Linux的测试环境下面。
参见:usleep()与sleep()类似,用于延迟挂起进程。进程被挂起放到reday queue.
在一般情况下,延迟时间数量级是秒的时候,尽可能使用usleep()函数。这样才能最佳的利用CPU时间。
时钟换算:
1s = 1000ms
1ms = 1000μs
1μs = 1000ns
1ns = 1000ps
在Git中执行以下命令,取消换行符自动转换操作
· Open Git Bash (开始菜单->AllPrograms->Git->Git Bash)
· 在命令行执行以下操作(使用鼠标右键复制和粘贴)
· 命令:gitconfig --global core.autocrlf false
遇到的坑和返回结果如下:
Bad Request
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { Connection: close Access-Control-Allow-Headers: Content-Type,Origin,Accept Access-Control-Allow-Methods: HEAD,GET,POST,PUT,DELETE,OPTIONS Access-Control-Allow-Origin: * Access-Control-Max-Age: 120 Keep-Alive: timeout=38 Date: Thu, 07 Jun 2018 08:55:02 GMT Content-Length: 5 Content-Type: text/plain; charset=UTF-8 } error
解决后正确示例:
c#:
private async void DoPostFile2(string sFile) { HttpClient client = new HttpClient(); MultipartFormDataContent form = new MultipartFormDataContent(); FileInfo file = new FileInfo(sFile); form.Add(new StreamContent(file.OpenRead()), "picFile", file.Name); HttpResponseMessage response = await client.
强制打酱油,不学习会使人落后
jquery获取子元素的一些方法
1.通过id,class等选择器
2.通过父元素进行find查找
3.通过父元素的children进行查找
注意:find和children的区别,代码已给出详细解释,想要真正理解,还是得靠代码.光看不练那都是纸上谈兵
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jQuery获取子元素的一些方法</title> <script type="text/javascript" src="js/jquery.js"></script> <script> $(function() { /* 1. 常用的 通过id,class选择器*/ /* * 2. 使用遍历的方法,通过find,find会跨越层级查找,一直找到 * 没有为止,但是children只会查找直接子元素 * */ $("button").on("click", function() { var str = $(".div1").find("p").eq(0).html(); /*这里取到的是 <p>我是间接的p元素</p>*/ $(".s1").html(str); /* * 通过children,下标从0开始,是取直接子元素,间接元素并不会遍历, * 也就是div1中的第一个p元素是间接子元素,并不会遍历到 * */ var str2 = $(".div1").children("p").eq(0).html(); /*这里取到的是 <p>上海<p/>*/ $(".s2").html(str2); }) }) </script> </head> <body> <div class="div1"> <div> <p>我是间接的p元素</p> </div> <p>1.上海</p> <p>2.广州</p> <p>3.北京</p> <p>4.深圳</p> <p>5.
实验一:实现顺序表的简单选择排序、直接插入排序、冒泡排序、快速排序、两路合并排序及堆排序。
简单选择.h
#include<iostream.h> template<class T> void SelectSort(T A[], int n) { int small; for (int i-0; i<n-1;i++){ small=i; for(int j=i+1;j<n;j++) if(A[j]<A[small])small=j; Swap(A[i],A[small]); } } 直接插入.h
#include <iostream.h>//直接插入排序 template <class T> void InsertSort(T A[], int n) { for(int i=1; i<n; i++){ int j=i; T temp=A[i]; while(j>0&&temp<A[j-1]){ A[j]=Al[j-1]; j--; } A[j]=temp; } 冒泡排序.h
#include <iostream.h> template <class T> void BubbleSort(T A[], int n) { int i,j,last; i=n-1; while(i>0) { last=0; for(j=0;j<i;j++) { if(A[j+1]<A[j]) { Swap(A[j],A[j+1]); last=j; } i=last; } } 快速排序
History对象描述:
History 对象包含用户(在浏览器窗口中)访问过的 URL。
History 对象是 window 对象的一部分,可通过 window.history 属性对其进行访问
History 对象最初设计来表示窗口的浏览历史。但出于隐私方面的原因,History 对象不再允许脚本访问已经访问过的实际 URL。唯一保持使用的功能只有 back()、forward() 和 go() 方法
History对象属性:
length:返回浏览器历史列表中的URL数量
History对象的方法:
back():加载history列表中的前一个URL
forward():加载history列表中的下一个URL
go():加载history列表涨的某个具体页面;经常用history.go(i) 前进或后退i个页面(i>0前进,i<0后退)
编写程序一直在用的配置文件类,感觉很好用,做一下总结:
.h
class inirw{ public: inirw(const char *filename){iniFileLoad(filename);}; ~inirw(){iniFileFree();}; //加载ini文件至内存 char gFilename[SIZE_FILENAME]; char *gBuffer; int gBuflen; int iniFileLoad(const char *filename); //释放ini文件所占资源 void iniFileFree(); int FindSection(const char *section, char **sect1, char **sect2, char **cont1, char **cont2, char **nextsect); //获取字符串,不带引号 int iniGetString(const char *section, const char *key, char *value, int size, const char *defvalue); //获取整数值 int iniGetInt(const char *section, const char *key, int defvalue); //获取浮点数 double iniGetDouble(const char *section, const char *key, double defvalue); int iniGetValue(const char *section, const char *key, char *value, int maxlen, const char *defvalue); //设置字符串:若value为NULL,则删除该key所在行,包括注释 int iniSetString(const char *section, const char *key, const char *value); //设置整数值:base取值10、16、8,分别表示10、16、8进制,缺省为10进制 int iniSetInt(const char *section, const char *key, int value, int base=10); // int iniGetIP(const char *section, const char *key, BasicHashTable *hashtable, int size, const char *defvalue); }; #endif .
IP协议概念 IP协议是将多个包交换网络连接起来,它在源地址和目的地址之间传送一种称之为数据包的东西,它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求。 IP协议不提供可靠的传输服务,它不提供端到端的或(路由)结点到(路由)结点的确认,对数据没有差错控制,它只使用报头的校验码,它不提供重发和流量控制。
IP协议报头格式 逐一介绍各个字段的含义:
4位版本号:指定IP协议的版本,对于IPv4来说就是4。4位首部长度:IP首部长度是多少个四字节。这里默认为0101也就是5。四位最大表示值为15,也就是说IP报头最大长度为60字节。8位服务类型:这里的八位前三位表示优先权字段(已经弃用),中间四位TOS字段,最后一位保留字段,其中保留字段必须设置为0。中间四位TOS字段分别表示:最小延时、最大吞吐量、最高可靠性、最小成本。(这里可见,这中间四位是以位位图的形式代表不同的情况)这四者冲突,只能选择一个,根据应用场景选择。16位总长度:IP数据报整体占多少字节8位生存时间(TTL):这里的生存时间指的是一个IP报文到达目的地的最大报文跳数。所谓报文跳数,就是从一个网络跳至另一个网络。每进行一次跳转,TTL的值就会减一。默认TTL的值为64。如果一个数据报的TTL减到0了还没有到达目的网络,么直接丢弃这个报文。引入生存时间的主要目的是防止在网络中有无限循环跳转的报文存在。8位协议:这里指的是IP层交付给上层的哪个协议。16位头部校验和:使用CRC进行校验,鉴别头部数据是否异常。32位源IP地址与目的IP地址:表示发送端及接收端。 接下来,重点讲述一下IP报头中第二行的三个字段。 在数据链路层,所能处理的最大数据包的大小是有限制的,类似于发快递时对包裹的尺寸大小限制。数据链路层以MTU来限制最大传输数据包的大小,如果在IP层的数据包大于MTU,那么发送端IP层会对数据包进行分片,一旦发送端对数据包进行分片了,那么接收端的IP层就会进行组装。既然要分片还得组装,那么同一个数据包分成多个片,这些片就得需要标识来确认它们是同一个包。而IP报头中的第二行的三个字段就是为了处理这个问题的。
16位标识:来自同一个数据包的不同片,它们的16位标识都是相同的,用16位标识来标记来自相同的数据包的分片。
3位标志:第一位保留,第二位设置为 1 的话,表示禁止分片,这个时候如果报文的长度超过了MTU就直接丢弃该报文。第三位更多分片,其实含义很简单,这个标志的作用是为了让接收端在进行组装的时候,判断一个数据包最后一片是什么。最后一片的此位设置为 1,其它的设置为 0。类似于结束标记。
13位片偏移:片偏移是分片相对于原始IP数据报的偏移量,也就是该片处于原始数据报的什么位置。实际偏移的字节数是这个数值 * 8得到的。也就是说除了最后一个报文以外,其它的分片报文长度必须是 8 的倍数,否则无法组装。
网段划分 由于网络的大量普及,以及发展,大量的网络产品产生。为了方便管理以及查找,必须要进行网段的划分。 IP地址分为两个部分,网络号与主机号。网络号保证两个相连的网段具有不同的标识。而主机号标识同一个网段内部不同的主机其主机号都不相同,但是其网络号相同。一个子网就是把相同网络号的所有主机放在一起,如果在子网中添加一个新的主机,那么这个主机的网络号与子网的网络号一致,主机号与子网内其它主机都不重复。
这样通过合理的设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同。由于手动管理分配IP地址不方便,于是引入一种叫做DHCP的技术,这种技术能够自动给子网内新加的主机划分IP地址,一般的路由器都有DHCP功能。
子网掩码划分网络号与主机号 子网掩码是一个32位的正整数,通常以一串“0” 结尾,将IP地址与子网掩码进行按位与操作,得到的结果就是网络号。网络号与主机号的划分只与子网掩码有关,与其它无关。 由此可见,IP地址与子网掩码按位与后得到网络号,主机号从全0到全1就是子网的地址范围。
特殊的 IP 地址 如果一个网络内的 IP 地址主机号为 0 ,那么这个时候代表网络号,该网络内的路由设备的 IP 地址的主机号是 1 。如果主机地址全部设置为 1 ,也就是主机号那里是 255 ,这个时候的 IP 地址就成为了广播地址,用于个同一个链路中相互连接的所有主机发送数据包。
如今计算机飞速发展,而使用IPv4 进行IP地址的划分是远远不够的,再加上前面的说的某些特殊的IP地址占用,IPv4仅今天四个字节,最多能表示43亿左右个IP地址,这肯定是不够的。那么该如何解决这个问题呢?前面说到利用 CIDR 进行网段的划分能够有效的环节了IP地址不够用的问题,但是实质上对于IP地址来说,其个数并没有增加,IP地址仍然不够用,如何解决?
解决方法主要有以下三种: 1. 动态分配IP地址:所谓动态分配IP地址就是说只给连接到网络中的主机分配IP地址,一但主机离开网络段,那么回收其IP地址。也就是说同一台MAC地址的主机设备,每次连接到网络当中,它的IP地址不一定都是相同的。 2. NAT技术:NAT技术又叫网络地址转换,实际上就是在进行网络连接时,进行IP地址的替换。所有使用本地地址的主机在和外界通信时,都要在NAT路由器上将其本地地址转换成全球IP地址,才能和因特网连接。 3. IPv6:既然四字节的IPv4不够用那么就创建一个更大的来表示 IP 地址,IPv 6 占16 个字节,也就是128个比特位。这个相比于 IPv4 来说就大得多,但是目前 IPv6 并没有普及。
私有IP地址与公网IP地址 如果一个区域内部有自己的局域网,并且IP地址只用于内部网络通信,那么按道理来说它们的 IP 地址可以是任意的,因为并不会对外网有任何的影响,但是 RFC 1918 规定了用于组建局域网内私有 IP地址的范围,如下:
0.文章学习 https://www.2cto.com/kf/201607/528696.html
1.使用场景 使用 adb bugreport 可以导出功耗分析所需文件,然后通过 https://github.com/google/battery-historian 进行更加详细的分析
adb bugreport > Bugreport.zip adb bugreport > Bugreport.txt adb bugreport - return all information from the device that should be included in a bug report.
" bugreport [PATH]\n" " write bugreport to given PATH [default=bugreport.zip];\n" " if PATH is a directory, the bug report is saved in that directory.\n" " devices that don't support zipped bug reports output to stdout.\n" 这里主要想知道 bugreport 的数据从哪里导出
作者:朱金灿
来源:http://blog.csdn.net/clever101
有时在访问共享文件夹时出现“不允许一个用户使用一个以上用户名与一个服务器或共享资源的多重连接”,下面谈谈如何解决这个问题。
1. 明确错误,错误截图如下:
2. 使用net use命令断开所有的连接,具体是在控制台中输入命令:net use * /del /y,如下图:
3. 使用net use命令重新建立连接,具体是在控制台中输入命令:net use \\192.168.30.240\ht "ht123456" /user:ht,其中ht123456为访问共享文件夹所设的密码,ht为用户名,如下图:
资料看的再多,不如自己手动操作一遍。
这里我吧框架搭建的步骤罗列出来,只要跟着步骤走,就能实现一个web框架的搭建。
本篇的任务:基本框架的搭建,并实现注册登录功能。
准备工作:
1、开发环境的准备
详细步骤不写出来了,非常简单,我把我的开发环境列出来。
2、jar包准备
这里我把spring的jar包全部导入到项目中,因为我的另一个工程比较大,所以全部导入了进去(也可以只导入必须的jar包)。
搭建步骤:
1、首先给大家看一下我的工程目录。
2、web.xml
都有注释,就不用细说了。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>myweb</display-name> <!-- 加载Spring容器配置 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 设置Spring容器加载所有的配置文件的路径 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext*.xml</param-value> </context-param> <!-- 配置SpringMVC核心控制器 --> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置初始配置化文件,前面contextConfigLocation看情况二选一 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!-- 启动加载一次 --> <load-on-startup>1</load-on-startup> </servlet> <!--为DispatcherServlet建立映射 --> <servlet-mapping> <servlet-name>springMVC</servlet-name> <!-- 此处可以可以配置成*.do,对应struts的后缀习惯 --> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 解决工程编码过滤器 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/pages/system/login/login.
一、前言知识 1、基于Region Proposal(候选区域)的深度学习目标检测算法
Region Proposal(候选区域),就是预先找出图中目标可能出现的位置,通过利用图像中的纹理、边缘、颜色等信息,保证在选取较少窗口(几千个甚至几百个)的情况下保持较高的召回率(IoU,Intersection-over-Union)。
2、什么是IoU?
Intersection over Union是一种测量在特定数据集中检测相应物体准确度的一个标准。我们可以在很多物体检测挑战中,例如PASCAL VOC challenge中看多很多使用该标准的做法。
通常我们在 HOG + Linear SVM object detectors 和 Convolutional Neural Network detectors (R-CNN, Faster R-CNN, YOLO, etc.)中使用该方法检测其性能。注意,这个测量方法和你在任务中使用的物体检测算法没有关系。
IoU是一个简单的测量标准,只要是在输出中得出一个预测范围(bounding boxex)的任务都可以用IoU来进行测量。为了可以使IoU用于测量任意大小形状的物体检测,我们需要: 1、 ground-truth bounding boxes(人为在训练集图像中标出要检测物体的大概范围); 2、我们的算法得出的结果范围。
也就是说,这个标准用于测量真实和预测之间的相关度,相关度越高,该值越高。
如下图: 下图展示了ground-truth和predicted的结果,绿色标线是人为标记的正确结果,红色标线是算法预测出来的结果,IoU要做的就是在这两个结果中测量算法的准确度。
Region Proposal方法比传统的滑动窗口方法获取的质量要更高。比较常用的Region Proposal方法有:SelectiveSearch(SS,选择性搜索)、Edge Boxes(EB)。
二、R-CNN、Fast R-CNN、Faster R-CNN三者关系 Faster R-CNN是基于R-CNN和Fast R-CNN来进行改进的。
三者关系 三者比较 关于R-CNN和Fast R-CNN更多细节请看R-CNN和Fast R-CNN
三、Faster R-CNN目标检测 3.1 Faster R-CNN的思想
Faster R-CNN可以简单地看做“区域生成网络RPNs + Fast R-CNN”的系统,用区域生成网络代替FastR-CNN中的Selective Search方法。Faster R-CNN这篇论文着重解决了这个系统中的三个问题: 1. 如何设计区域生成网络; 2. 如何训练区域生成网络; 3.
上一篇参考安装配置IIS+MySQL+PHP环境的详细教程之篇一IIS安装
安装配置IIS+MySQL+PHP环境的详细教程(之篇二PHP安装) 在Windows 云服务器中进行 PHP 配置,需要完成 IIS 角色的添加和安装,详细请见我的上一篇文章安装配置IIS+MySQL+PHP环境的详细教程之篇一IIS安装
本文介绍PHP 5.3 之后版本的安装 PHP 5.3 版本后取消了安装包模式,仅通过 zip 文件和 debug pack 两种方式进行安装。本例使用 Windows Server 2012 R2 环境下 zip 安装进行示例。
1、在云服务器中下载 PHP zip 安装包(下载地址: http://windows.php.net/download/ )。 注意:在 IIS 下运行时必须选择 Non Thread Safe(NTS) 的 x86 包。若一定要在 Windows Server 32bit (x64) 下,PHP 选择 x64,则不能选择 IIS,此时可使用 Apache 作为代替选项。
选择类似如下的安装包: 2、PHP 5.3 以上版本的安装依赖于 Visual C++ Redistributable Update 。请根据下载的 PHP 安装包名,参考如下表格所示的对应关系下载并安装 VC Update 安装程序:
PHP安装包名Visual C++ Redistributable安装包下载地址php-x.x.x-nts-Win32-VC14-x86.ziphttps://www.microsoft.com/zh-cn/download/details.aspx?id=48145php-x.x.x-nts-Win32-VC11-x86.ziphttps://www.microsoft.com/zh-cn/download/details.aspx?id=30679php-x.x.x-nts-Win32-VC9-x86.ziphttps://www.microsoft.com/zh-cn/download/details.aspx?id=5582 若下载的 PHP 安装包如下图所示: 则按表格第一行对应关系下载 VS 2015 版本的安装包,下载并安装如下两个.
上一篇参考腾讯云学生机购买与配置
安装配置IIS+MySQL+PHP环境的详细教程(之篇一IIS安装) Windows 2012 R2 版本示例 1、登录云服务器 打开“运行”(Windows系统win+R键),输入mstsc进入远程服务器登录界面 2、登录 进入Windows 云服务器后,单击左下角【开始(Start)】,选择【服务器管理器(Server Manager)】,打开服务器管理界面,如下图所示: 3、选择【添加角色和功能】,在 ”选择安装类型“页面 中选择【基于角色或基于功能的安装】,单击【下一步】按钮: 4、在窗口选择下一步,到”服务器角色“选项卡,勾选【Web服务器(IIS)】,在弹出框中单击【添加功能】按钮后,单击【下一步】按钮:(展开把web服务器下的所有选项都勾选上) 5、在 ”功能“选项卡 中勾选 .Net3.5 ,单击【下一步】按钮后,选择 ” Web 服务器角色(IIS)“选项卡 同时单击【下一步】: 6、在 ”角色服务“选项卡 中,勾选【CGI】选项,单击【下一步】: 7、确认安装并等待安装完成: 8、安装完成后,在云服务器的浏览器中访问 http://localhost/ 验证是否安装成功。出现以下界面即为成功安装:
今天就说一说js中的数据、内存和变量吧。之前一直对变量关注的比较多,而忽视了内存和数据以及它们三者之间的关系,今天就在这里补一波。
一、js中的数据指的是什么? 数据在人们眼中向来都是一个非常抽象的事物,它无处不在,但是我们总是不知道怎么去描述它。而js中的数据,我认为它是指:在内存中可读的, 可传递的、保存了特定信息的“东西”,是我们在内存中所操作的目标。一个函数是数据、一个常量是数据、一个对象也是数据。
二、js中的变量 说完了数据,接下来说一下变量。变量这个词相信大家都听说过无数次了,有些人可能会说:“变量不就是通过var 声明的一个东西吗?”这样理解并不是完全正确,例如,我们不使用var,直接a = 1,这样也会声明一个变量。 我所理解的变量:变量就是在程序运行过程中它的值允许改变的量。 一个变量对应一块小内存, 它的值保存在此内存中。变量常常包含两部分:变量名和变量的值。
三、js中的简单内存模型 唉?你说了这么多到底什么是内存啊? 我们可以把内存理解为*内存条通电后产生的(临时的)存储空间。一块内存包含2个方面的数据:内部存储的数据和地址值数据。在js的内存模型中内存分为可以分为三个部分: 常量池:存放常量的内存区域。 栈空间:存放全局变量和局部变量的内存区域。 堆空间: 存放对象等复杂数据类型的内存区域。 听起来是不是很抽象,下面上图: 我们存放一个常量时,将其存放在常量池中,保存常量名称和常量的值。在这里主要是说一下栈空间和堆空间。栈空间用来存放全局变量和局部变量,如果该变量是基本数据类型,那么栈空间存储该变量的名称和值。例如,var a = 1; 我们会在栈空间中开辟一块新的内存,存放变量的名称a和变量的值1。如果该变量是复杂数据类型(对象),那么栈空间存放变量名称和该对象在堆空间中的地址值。例如,var b = {n : 1,m : 2}; 我们会在堆空间中开辟一块内存存放对象{n : 1,m : 2},同时在栈中开辟一块内存空间存放变量名b和该对象在堆空间的地址值0x123。 了解了这JavaScript简单的内存结构,我们下面来看一看几个有趣的代码片段吧。
四、几个有趣的代码片段 4.1、js中,变量的比较是栈中存放该变量的内存的内容(值或地址值)的比较,对存放基本数据类型的变量来说,栈中存放的是该变量的名称和值;对存放复杂数据类型(对象)的变量来说。栈中存放的是该变量的名称和地址值,而对象的具体内容存放在堆中。 下面上代码一:
var obj1 = {n : 1}; var obj2 = {n : 1}; console.log(obj1 === obj2);//false 咦,为什么obj1和obj2的内容看上去明明相等,但是会返回false呀?这就涉及到了js内存模型的知识。参考上面的js内存模型图,我们可以看到,在执行var obj1 = {n : 1};时,会在堆中开辟一个新的空间存放obj1对象的具体内容,同时把新空间的地址存放在对应的栈中,执行第二行时同理。所以obj1和obj2保存的其实是两个不同的地址值,所以它们不可能相等。 如果把代码改成下面这个样子:
var obj1 = {n : 1}; var obj2 = obj1; console.
package com.company; import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ThreadLocalDo { public static void main(String[] args) { final Data data = new Data(); for (int i = 0; i < 3; i++) { new Thread(new Runnable() { public void run() { for (int j = 0; j < 5; j++) { data.set(new Random().nextInt(30)); } } }).start(); } for (int i = 0; i < 3; i++) { new Thread(new Runnable() { public void run() { for (int j = 0; j < 5; j++) { data.
原因android studio 挂掉
第一种方法:关机重启android studio;
第二种方法:5037端口被占用;打开cmd,输入:netstat -ano | findstr "5037";
(1) tasklist|find "4168" 找到占用5037端口的PID,打开任务管理器,将对应pid号的进程杀死;
(2) taskkill |pid PID 直接kill掉被占用的端口; (PID:占用5037端口的PID)
第三种方法:重启adb,找到你的sdk所在目录,打开cmd,依次输入
输入:cd C:\Users\xxx\AppData\Local\Android\sdk\platform-tools (xxx表示省略路径),切换到sdk的目录下
输入:adb kill-server
输入:adb start-server
参考链接:
https://blog.csdn.net/yanche521/article/details/50977301
https://www.cnblogs.com/-wang-cheng/p/4973021.html
一、阻塞型延时 阻塞的原理就是:在延时期间,本线程的事件循环得不到执行。
1、QThread类的sleep() 最简单的延时方法就是使用QThread类的sleep(n)、msleep(n)、usleep(n),这几个函数的不良后果就是,GUI会在延时的时间段内失去响应,界面卡死,所以,这三个函数一般用在非GUI线程中。
QThread::msleep(50);//阻塞延时50ms 2、使用定时器:死等 void Delay_MSec_Suspend(unsigned int msec) { QTime _Timer = QTime::currentTime().addMSecs(msec); while( QTime::currentTime() < _Timer ); } 二、非阻塞延时 原理无非就是利用事件循环,有两种原理:
1、处理本线程的事件循环 在等待中,不断强制进入当前线程的事件循环,这样可以把堵塞的事件都处理掉,从而避免程序卡死
void Delay_MSec(unsigned int msec) { QTime _Timer = QTime::currentTime().addMSecs(msec); while( QTime::currentTime() < _Timer ) QCoreApplication::processEvents(QEventLoop::AllEvents, 100); QCoreApplication::processEvents(QEventLoop::AllEvents, 100);//这条语句能够使程序在while等待期间,去处理一下本线程的事件循环,处理事件循环最多100ms必须返回本语句,如果提前处理完毕,则立即返回这条语句。这也就导致了该Delay_MSec函数的定时误差可能高达100ms。
2、使用子事件循环 创建子事件循环,在子事件循环中,父事件循环仍然是可以执行的
void Delay_MSec(unsigned int msec) { QEventLoop loop;//定义一个新的事件循环 QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数 loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出 } 三、耗时代码的处理 假设有这样的应用情景:点击某个button之后,需要读入并处理一幅图像,需要耗时20秒才能处理完。
在这20s内,GUI会失去效应,界面上的任何元素都无法被点击,这种情况应该怎么办?方法有两种:1、用另一个线程去处理这个耗时任务;2、在耗时任务中,不断地去处理本线程的事件循环,以保证GUI的及时响应。
这里重点说一下第2种,参考https://blog.csdn.net/dbzhang800/article/details/6554104
for(i=0; i < 1000000; i++) { //QCoreApplication::processEvents(QEventLoop::AllEvents); //去处理本线程的事件循环,避免本线程被堵塞 QCoreApplication::processEvents(QEventLoop::AllEvents, 5);//如果不够频繁,可以增加第二参数来缓解卡顿 for(j=0; j < 1000000; j++) { //QCoreApplication::processEvents(QEventLoop::AllEvents);//处理事件循环,不建议放在这里,可能过于频繁 doSomeThing(); } } 一般来说,processEvents()不宜被调用的过于频繁,也不宜被调用的不够频繁。过于频繁的话,一方面会使线程的响应更好,但另一方面会导致原本就耗时的任务变得更加耗时;不够频繁的话,显然可能会使GUI线程的响应变差,例如每500ms才被调用一次,那么GUI的事件循环就只能500ms才被处理一次,当然,这个问题可以通过设定processEvents()的第二个形参略微得到缓解,更好的做法是,保证被调的周期<200ms(再小一些更好,看程序需求),这样不至于肉眼可见的卡顿。
//去除复制样式的方法 function textInit(e) { e.preventDefault();//阻止默认事件 var text; var clp = (e.originalEvent || e).clipboardData; if (clp === undefined || clp === null) { text = window.clipboardData.getData("text") || ""; if (text !== "") { if (window.getSelection) { var newNode = document.createElement("span"); newNode.innerHTML = text; window.getSelection().getRangeAt(0).insertNode(newNode); } else { document.selection.createRange().pasteHTML(text); } } } else { text = clp.getData('text/plain') || ""; if (text !== "") { document.execCommand('insertText', false, text); } } } 首先 需要在可编辑div上绑定 paste 监听函数
centos7重启网络报错,提示用 systemctl status metwork.service 查看细节, 运行 systemctl status metwork.service后报这样的错:
systemctl status metwork.service 多方百度Google,大部分都说真么MAC地址池冲突什么之类的,试验之后都不行。 最后还是用最简单的方法搞定了。
解决办法:
systemctl stop NetworkManager 再重启:
systemctl restart network.service
二分法查找从概念上很好理解,困难的地方在于有几个细节需要注意:
1.循环执行条件。
2.递进方式。
3返回值的问题,返回左右边界值还是返回一个存储结果的中间变量。
以一个最常见的游戏为例,甲从0~9中随便选择一个整数,乙来猜,甲回答大于,小于,或等于,若甲选择的数字为9,则乙在大概率下,最快几次可以猜到。
(0+9)/2 = 4 (0 + 4)/2=2 (0+2)/2=1 (0+1)/2=0 (0+0)/2=0; left = right; result = left;
(0+9)/2 = 4 (5 +9 )/2=7 (5+7)/2=6 (5+6)/2=5 (5+5)/2=5; left = right;result=left;
(0+9)/2 = 4 (4 +9 )/2=6 (6+9)/2=7 (7+9)/2=8 (8+9)/2=8 死循环
最后一种情况进入死循环,可以看出由于整数除法只保留整数位,所以left在每次更新的时候必须等于mid +1;
倘若游戏规则改为甲只能回答小于,大于等于两种
(0+9)/2 = 4 (0 + 4)/2=2 (0+2)/2=1 (0+1)/2=0 (0+0)/2=0; left = right; result = left;
(0+9)/2 = 4 (5 +9 )/2=7 (5+7)/2=6 (5+6)/2=5 (5+5)/2=5; left = right;result=left;
通常在添加控件时,使用Qt Designer拖动就可以了,但是偶尔也会遇到需要使用代码动态添加控件的时候。
在需要动态增减空间的部件上添加一个布局控件,然后在布局上增减控件,这样部件大小会跟着变化。新增控件时,名称不要重复。新增控件时,需要设置最小宽高,以免加入布局后缩到最小。删除控件时,一定要在父部件上找,而不是在布局上。删除空间时,先判断指针空间是否为空。 添加控件:
QWidget *w = new TocPannel; w->setObjectName("toc"); QHBoxLayout * horizontal_layout = ui->verticalLayout; horizontal_layout->setDirection(QBoxLayout::TopToBottom); horizontal_layout->setAlignment(Qt::AlignTop) horizontal_layout->addWidget(w); 删除控件:
QWidget *w = this->findChild<QWidget *>("toc"); ui->horizontalLayout->removeWidget(w); w->deleteLater(); 为了避免在清空Layout时删除空间对象,也可以使用如下方式来清空Layout
ui->horizontalLayout->removeWidget(w); w->setParent(nullptr);
1.如何取到set集合的第一个元素。
public static void main(String[] args) { Set set = new HashSet(); set.add("xixi"); set.add("haha"); set.add(123); set.add(1.2); System.out.println(set);//[1.2, haha, xixi, 123] //第一种方法 if(!set.isEmpty()){ System.out.println(set.iterator().next());// 1.2 } //第二种方法:将set集合转换成list集合 取第一个 List list = new ArrayList(set); System.out.println(list.get(0));// 1.2 } 2.MySql中知识点。
01. int占的字节数:int类型占4个字节
02.tinyint(1) 和 tinyint(3) 没什么区别,占用字节都是一位,存储范围都是一样的
03.tinyint(3) zerofill ,当插入的数据少于3位的时候,左边自动补零,这才是限制显示长度
04.int(1) 和 tinyint(1) ,够用的情况下,优先选择tinyint(1),因为占字节少、节省空间。
05.tinyint一个字节 smallint 两个字节 MEDIUMINT三个字节 int 4个字节 BIGINT 8个字节。
06.但是,varchar(5) 这里的5 限制的是储存字符的个数,字符不分贵贱(不分 中文、英文、数字...)。
小结:
tinyint一个字节 smallint 两个字节 MEDIUMINT三个字节 int四个字节
不管 tinyint 后面的数字是多少,它存储长度=2^(1字节)=2^8,即存储范围是 -2^7 到 2^7 - 1。
基于python的信用卡评分模型
1. 项目背景介绍 1.1 信用风险和评分卡模型的基本概念 信用风险指的是交易对手未能履行约定合同中的义务造成经济损失的风险,即受信人不能履行还本付息的责任而使授信人的预期收益与实际收益发生偏离的可能性,它是金融风险的主要类型。
借贷场景中的评分卡是一种以分数的形式来衡量风险几率的一种手段,也是对未来一段时间内违约、逾期、失联概率的预测。一般来说,分数越高,风险越小。
信用风险计量体系包括主体评级模型和债项评级两部分。其中主体评级模型包含以下四个方面内容:
申请者评级模型:主要应用于相关融资类业务中新用户的主体评级,适用于个人及机构融资主体。位于贷前准入环节。行为评级模型:主要用于相关融资类业务中存量客户在续存期内的管理,如对客户可能出现的逾期、延期等行为进行预测,仅适用于个人融资主体。 催收评级模型:主要应用于相关融资类业务中存量客户是否需要催收的预测管理,仅适用于个人融资主体。 欺诈评级模型:主要应用于相关融资类业务中新客户可能存在的欺诈行为的预测管理,适用于个人和机构融资主体。 在贷前准入环节里面。 本项目主要针对申请者评分模型。
1.2 数据来源 本项目数据来源于kaggle竞赛Give Me Some Credit。
2. 信用卡评分模型开发 模型的构建主要包含以下几大部分内容:数据准备及数据预处理、变量选择、模型构建、模型验证、模型评估、模型部署、模型监控几大部分。下面一一讲述。
2.1 数据准备及数据预处理 2.1.1 获取数据 数据获取包括存量客户包括获取存量客户及潜在客户的数据。存量客户是指已经在证券公司开展相关融资类业务的客户,包括个人客户和机构客户;潜在客户是指未来拟在证券公司开展相关融资类业务的客户,主要包括机构客户,这也是解决证券业样本较少的常用方法,这些潜在机构客户包括上市公司、公开发行债券的发债主体、新三板上市公司、区域股权交易中心挂牌公司、非标融资机构等。
首先我们来观察现有的数据及指标。
本项目数据来源于kaggle竞赛Give Me Some Credit。其中训练数据共计15万条。
变量名
描述
类型
标号
SeriousDlqin2yrs
超过90天或更糟的逾期拖欠
Y/N
Y
RevolvingUtilizationOfUnsecuredLines
贷款以及信用卡可用额度与总额度比例
百分比
x0
age
借款人当时的年龄
整型
x1
NumberOfTime30-59DaysPastDueNotWorse
35-59天逾期但不糟糕次数
整型
x2
DebtRatio
负债比率
百分比
x3
MonthlyIncome
月收入
real
x4
NumberOfOpenCreditLinesAndLoans
开放式信贷和贷款数量,开放式贷款(分期付款如汽车贷款或抵押贷款)和信贷(如信用卡)的数量
整型
x5
NumberOfTimes90DaysLate
90天逾期次数:借款者有90天或更高逾期的次数
整型
x6
NumberRealEstateLoansOrLines
症状:
安装了mysql 8.0.11 之后本地可以登录,但是远程第三方工具无法连接,防火墙已经放通的,
解决之道:
首先登陆到mysql命令行:
mysql -u root -p 进入之后选择mysql库,用户信息都存在这个库的user表中
mysql>use mysql; mysql>update user set host='%' where user='root' AND host='localhost'; mysql>FLUSH PRIVILEGES; 测试连接。用 Navicat 连接数据库就可以正常连接了。
另,给普通用户远程连接的权限:
1、授权 myuser 用户对指定库的所有表,所有权限并设置远程访问
GRANT ALL ON 指定库.* TO 'myuser'@'%'; 2、更新 该 用户密码
ALTER USER 'myuser'@'%' IDENTIFIED WITH mysql_native_password BY 'yourpassword'; 3.刷新权限
FLUSH PRIVILEGES;
进阶的爬虫系列 ——不得不说的贴吧爬取术 感谢各位能点开我的这篇博文,才开始写,这个算是很简单的爬虫,文中如有错误和不足欢迎各位大神多多包涵指正,大家的建议是我不断前行的动力,废话不多说我们直接进入主题。
目标:爬取贴吧数据 步骤: 首先我们进入百度贴吧的页面,通过进入不同的贴吧以及翻页解析其url的变化规律 通过观察我们可以看出 “kw=”的后面是接的贴吧的名字,而“pn=”的后面是接的页数,从0开始,每翻一页pn对应的数值会加50。发现规律以后我们就可以通过url中贴吧名字及页数这两个点用循环遍历爬取页面数据。
然后我们明确业务逻辑: 定义一个类——>初始化——>构造url列表——>遍历,发送请求,获取响应——>保存 根据业务逻辑构建初始代码如下:
# coding=utf-8 class Tieba: def __init__(self,tieba_name): self.url_temp ="https://tieba.baidu.com/f?kw=" + tieba_name + "&ie=utf-8&pn={}" self.headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" } def get_url_list(self): # 构造url列表 pass def parse_url(self,url): # 发送请求,获取响应 pass def save_html(self,html_str,page_num): # 保存html字符串 pass def run(self):#实现主要逻辑 #1.构造url列表 #2.遍历,发送请求,获取响应 #3.保存 pass if __name__ == '__main__': tieba = Tieba('李毅') tieba.run() 1.初始化url路径,和请求头
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Exception in thread "main" java.lang.NoClassDefFoundError: io/netty/util/Timer at com.datastax.driver.core.Configuration$Builder.build(Configuration.java:294) at com.datastax.driver.core.Cluster$Builder.getConfiguration(Cluster.java:1247) at com.datastax.driver.core.Cluster.<init>(Cluster.java:116) at com.datastax.driver.core.Cluster.buildFrom(Cluster.java:181) at com.datastax.driver.core.Cluster$Builder.build(Cluster.java:1264) at com.flx.test.FirstDemo.main(FirstDemo.java:13) Caused by: java.lang.ClassNotFoundException: io.netty.util.Timer at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) ... 6 more Caused by: java.util.zip.ZipException: invalid LOC header (bad signature) at java.
import torch import torch.nn as nn import torch.nn.functional as F from torch.autograd import Variable import numpy as np input = Variable(torch.Tensor([[[1, 3, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]], [[1, 3, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]]])) print("input shape",input.shape) c = F.avg_pool1d(input, kernel_size=3, stride=2) print(c) print("c shape:",c.shape) # m = nn.AvgPool2d(3, stride=2) m = nn.AvgPool2d((2, 2), stride=(2, 2)) input = Variable(torch.
转:http://www.xuebuyuan.com/935987.html
背景:在我们的计算机中图像是以RGB888格式显示图像的,24位图每个像素保存了32bit的数据,即RGB888+Alpha,Alpha就是半透明填充字节……但是对于真彩的图像而言,肉眼在16bit的时候已经难以分辨了,因此,有些时候,可以讲RGB888转换为RGB565来存储,减少了存储器的容量的同时,降低了数据量;在后端显示的时候,再次把RGB565转换为RGB888,实现数据宽度的匹配!!
题记: 总的思想就是,低位增加或者移除。
一.RGB888->RGB565
方法只要提取相应单色高位即可(R5 G6 B5),但会导致低位的缺失,影响精度,而且无法恢复。
二.RGB565->RGB888
方法只要补充相应单色低位即可(R3 G2 B3)。
RGB888用unsigned int 32位字节存储 0 0 0 0 0 0 0 0R7R6R5R4R3R2R1R0G7G6G5G4G3G2G1G0B7B6B5B4B3B2B1B0 RGB565用unsigned short 16位字节存储 R7R6R5R4R3G7G6G5G4G3G2B7B6B5B4B3 #define RGB888_RED 0x00ff0000
#define RGB888_GREEN 0x0000ff00
#define RGB888_BLUE 0x000000ff
#define RGB565_RED 0xf800
#define RGB565_GREEN 0x07e0
#define RGB565_BLUE 0x001f
unsigned short RGB888ToRGB565(unsigned int n888Color)
{
unsigned short n565Color = 0;
// 获取RGB单色,并截取高位
unsigned char cRed = (n888Color & RGB888_RED) >> 19;
unsigned char cGreen = (n888Color & RGB888_GREEN) >> 10;
今天一开机,C盘爆红,只有2G空间,明明前几天还有十几G。也懒得去管什么文件占这么大空间,反正要重装系统,就干脆直接重装系统吧。
用360点系统重装大师,还真的是很方便,什么都不用管,28分钟就重装好了。什么驱动之类的,都OK,真都是拎包入住。唯一的就是人家要给自己打广告,360全家桶给你都安装好了。
系统重装后,开始安装Android studio,之后开始开工。发现C盘空间使用又很快,那我估计应该就是Android studio搞的鬼。因为刚装的系统,其他软件都还没有安装。
上网一查,还真是Android studio的事,网上也有很多人给出了解决办法。我就不重复都贴了。使用之后,效果甚好,对固态硬盘C盘不多的,很受用。
链接:配置Android Studio的缓存文件路径(释放你的C盘)
这篇文章中,关于.android路径到设置,有2点需要注意:
ANDROID_SDK_HOME的路径,并不是要设置SDK目录的路径。完全可以重新设定一个新路径,见文章:android 修改AVD的存放位置,否则真要设置为SDK的路径,Android studio反而会警告提示。修改ini文件的路径,是要进入到.android目录里面去,进入avd目录。当你设置了虚拟机,那么设置相应当虚拟机当ini文件。
package com.dwtedx.income.utility; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by dwtedx(qinyl)(http://dwtedx.com) on 16/9/2. * Company DD博客 * Description java字符串加法运算 */ public class ReportUtil { /** * 格式化数字 * @param obj 数字对象 * @param format 格式化字符串 * @return */ public static String formatNumber(Object obj, String format) { if (obj == null) return ""; String s = String.valueOf(obj); if (format == null || "".equals(format.trim())) { format = "
新装的debain系统输入ll命令显示下面这样, command not found
user@debian:~$ ll -bash: ll: command not found 命令不存在,what? 哥哥用centos好多年,这个命令不存在,在逗哥哥吗?
虽然都知道ll 就是 ls -l 的缩写,但是用惯了centos,还是不台想打一个 ls -l 的. 解决办法如下: vim ~/.bashrc 找到下面这行,取消掉注释(去掉#)。
#alias ll='ls -l' 保存退出。 然后使之生效: user@debian:~$ source ~/.bashrc 就可以用了。
ll 可以用了,问题又来了,ll之后,文件了目录同一个色儿,看着很不爽。 解决办法: 同样是编辑这个文件: vim ~/.bashrc 找到
#alias dir='dir --color=auto' 去掉注释,保存退出,使之生效。 source ~/.bashrc 就可以正常使用了。
一、多线程优点
1.可以把占据上时间的程序中的任务放到后台去处理
2.用户界面更加人性化,任务进度条
3.程序运行速度可能加快
4.在一些等待任务实现上入用户输入、文件读写和网络收发数据等,能释放一些资源比如内存占用等
二、线程跟进程区别
每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
线程可以被抢占(中断);其它线程运行时,线程可以暂时搁置
三、线程分类
内核线程:由操作系统内核创建和撤销
用户线程:不需要内核支持而在用户程序中实现的线程
四、线程常用的两个模块
_thread threading
_thread.start_new_thread ( function, args[, kwargs] ) 参数说明:
function - 线程函数。args - 传递给线程函数的参数,他必须是个tuple类型。kwargs - 可选参数。 #!/usr/bin/python3 import _thread import time # 为线程定义一个函数 def print_time( threadName, delay): count = 0 while count < 5: time.sleep(delay) count += 1 print ("%s: %s" % ( threadName, time.ctime(time.time()) )) # 创建两个线程 try: _thread.start_new_thread( print_time, ("Thread-1", 2, ) ) _thread.
在Android 5.0之前,vold中的磁盘加密功能FDE(full disk encryption),只是对用户密码及SALT采用了scrypt算法来生成加密密钥(4.4以前使用pkdf2,强度更低),这些只是增加了暴力破解的难度,但风险依然很高。比如可以获取分区镜像 前1K 及 后16K 的数据 (Android FDE的相关加密密钥默认存储在分区尾部的16 KBytes中,前4K是EXT4文件系统的Superblock,一般EXT4 FS SuperBlock前1K均为0),暴力枚举用户密码,并采用vold中相同的磁盘加密算法来生成解密密钥,尝试用其对前1K中的部分数据进行AES算法解密,解出来都为0则碰撞OK。默认Android原生的用户密码6位数字密码,即使很普通的PC 3、5个小时都能跑出来。 从5.0开始,增加了硬件TEE(Trusted Execution Environment)中的签名过程,结合多次scrypt算法来产生加密密钥,以此密钥来加密 磁盘加密主密钥,使得离线暴力破解几乎无可能,除非破解者获得了TEE中的RSA私钥,并清楚特定硬件平台HAL中的keymaster模块实现。 5.0中的加密 磁盘加密密钥 的实现逻辑: 1. 产生随机16 Bytes DEK(disk encryption key--磁盘加密用的密钥)及16 Bytes SALT; 2. 对(用户密码+SALT)使用scrypt算法产生32 Bytes HASH 作为IK1(intermediate key 1); 3. 将IK1填充到硬件产生的私钥规格大小(目前看到是RSA算法,256Bytes), 具体是: 00 || IK1 || 00..00 ## one zero byte, 32 IK1 bytes, 223 zero bytes. 4. 使用硬件私钥 HBK 对 IK1 进行签名,生成256 Bytes签名数据作为IK2; 5. 对(IK2+SALT)使用scrypt算法(与第二步中的SALT相同)产生出32 Bytes HASH 作为IK3; 6. 使用IK3前16 Bytes作为KEK(用来加密主密钥DEK的KEY),后16 Bytes作为算法IV(初始化向量); 7.
try catch里面try catch嵌套
点击打开链接
try 与catch的作用 首先要清楚,如果没有try的话,出现异常会导致程序崩溃。而try则可以保证程序的正常运行下去,比如说: try{ int i = 1/0; }catch(Exception e){ e.printStackTrace(); } 一个计算的话,如果除数为0,则会报错,如果没有try的话,程序直接崩溃。用try的话,则可以让程序运行下去,并且输出为什么出错!try的话,配合log4j使用会对程序的日后维护帮助很大。 那么e.printStackTrace();是什么意思? 当try语句中出现异常是时,会执行catch中的语句,java运行时系统会自动将catch括号中的Exception e 初始化,也就是实例化Exception类型的对象。e是此对象引用名称。然后e(引用)会自动调用Exception类中指定的方法,也就出现了e.printStackTrace();。printStackTrace()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因。(这是白话解释,比较容易理解) try{//代码区}catch(Exception e){//异常处理}代码区如果有错误,就会返回所写异常的处理。
先说下项目背景,公司的项目原来用的kisso+shiro,但是kisso太小众了,性能各方面也不满足要求,所以老大要更换springboot+cas+shiro+pac4j集成,楼主在资料极少的情况下弄了很久还是没配置好shiro+pac4j,项目老大奋斗到深夜给解决了,所以写一篇博客造福小白了!
首先下载cas,下载5以上的版本 https://github.com/apereo/cas-overlay-template
编译 解压zip,命令行进去,执行mvn clean package 结束之后会出现 target 文件夹,里面有war包啥的,把war包解压,比如我们把解压后的文件夹命名为 cas_war 吧,后文提到 cas_war 就代表是这个文件夹
本地配置tomcat通过https访问 注意以下所有命令除了文件路径最好都跟我的保持一致,比如alias,就用tomcat不要换别的,省的小白出问题 命令行里cd进入%JAVA_HOME%/bin目录,配置了环境变量就不用了
1.执行:
keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "E:\projects\hugeo\cas\tomcat.keystore" 按照以下输入:
密钥库口令:123456(这个密码非常重要) 名字与姓氏:www.hugeo.com(域名很重要,建议自己编个域名,在host文件里写好映射,host的使用百度吧) 组织单位名称:anything(随便填) 组织名称:anything(随便填) 城市:anything(随便填) 省市自治区:anything(随便填) 国家地区代码:anything(随便填) 现在E:\projects\hugeo\cas\tomcat.keystore这个文件生成了
2.继续执行:
keytool -export -file E:\projects\hugeo\cas\cas.crt -keystore E:\projects\hugeo\cas\tomcat.keystore -alias tomcat 用刚刚的tomcat.keystore文件生成了cas.crt文件
3.导入授权文件到jdk并设置密码:
keytool -import -file E:\projects\hugeo\cas\cas.crt -alias tomcat -keystore E:\programFiles\Java\jre1.8.0_131\lib\security\cacerts -storepass 123456 注意-storepass 123456是设置此步骤的密码的,第一次执行命令设置之后以后再执行这个命令就不要带这个参数了,然后输入密码的时候输第一次设置的密码,这个密码和生成keystore的密码可以不一样,设置成一样的比较方便防止搞混
要删除也很容易: keytool -delete -alias tomcat -keystore E:\programFiles\Java\jre1.8.0_131\lib\security\cacerts
(如果导入的时候没有设置别名就再导入一次,会显示别名)
5.修改tomcat的配置文件server.xml
删掉:
<Connector port="
在服务器端如何获取tomcat中部署的所有项目的项目名称?
有个疑惑?如果我的tomcat中部署了6个项目,那我在服务器端如何能获取到这6个项目的项目名称呢?用jsp的内置对象request.点什么方法或者属性能获取到tomcat中部署的所有项目的项目名称?请知道的人告诉我!