先来说说什么是RUDP,RUDP全称Reliable User Datagram Protocol,译文为可靠的UDP传输。
准确的说RUDP应该是一种概念,而不是某个开源库。他是利用UDP无连接的特性中的优点,通过模拟TCP的可靠性传输来实现。
换句话说,从OSI模型或常规的四层网络模型的角度说,本质上就是一个UDP协议的通讯机制,只不过认为的加入了TCP中的握手、重传等功能。虽然有相应的标准规范给了RUDP一个身份,但可以看做一种应用层协议。
RUDP概念实现的协议有很多,由最初的RUDP库,也有后来用的较多的UDT,也有现在的SRT等等。
UDT:起初在做P2P网络传输的时候,当时用的是UDT(已经停更很久了),现在网上放眼望去也出现很多RUDP概念的实现。这个库据说是,当年提出RUDP概念的作者所做,由于是半路参与P2P传输这块,也就无从得知为何要选择UDT,但后来从UDT的写代码来看,UDT实现的侧重点在于如何模拟TCP进行可靠的传输,并尽量处理好UDP的分组问题,对于传输的效率方便考虑并不是考虑很多。在非实时和大吞吐量传输中还是具备一定的优势(尤其是可靠性方面)。
RUDP(非开源):这是当前接触到的,看着代码不太像网上某个具体的库,而很像多个库中的实现理论依据“粘合”出来。这个代码与业务的耦合性非常高,不是一套纯粹协议栈的代码,其中比较“机智”的利用了业务特性来节省掉纯协议上的可靠性实现,代码看上去要去UDT在协议实现部分会“短小精干”不少,估计在所谓“性能”上应该会比UDT好一些(cpu执行效率,因为要传输音视频数据),但这个库存在的问题实际上要比“UDT”严重很多,因为这套代码并没有在传输上做太大优化,导致在需要做稍微大一点的吞吐时,数据经常被拥塞(堵住)。随着现在带宽越来越大,小运营商也越来越让人抓狂,加上网络承载数据逐渐增加,这套RUDP代码已经不够用了,除了所谓的CPU执行效率较高以外,网络传输效率低的可怜,对带宽的有效利用率非常低。
SRT:从官方的README来看,并通过和最后一个版本的UDT代码做了比较之后发现,事实上SRT的代码确实源自UDT,并且在这个基础上做了ARQ,Buffer控制的改进,加密功能。
并没有完完整整的去看并理解SRT,仅从代码差异上的走马观花式的来看,SRT确实有着跟灵敏的丢包感知和处理,这也是ARQ的一个特性之一。同时在Buffer的控制上,增加了Buffer的双端反馈机制。主观上理解,SRT的吞吐能力应该会比原始的UDT代码弱一些,并且带宽的有效利用率可能会差一些。因为侧重点在于实时性,因此可能会对带宽的有效利用率做出一定的牺牲,在P2P传输场景下,可能还好说,但对于P2SP的情况下,可能会对服务器带宽的需求有一定的增加。
尤其是这个buffer控制,很耐人寻味,没有详细看,不是很清楚有没有特意做了数据的分段/分组优化。
后续还需要认真看看SRT的代码,详细的了解一下整个机制的发挥情况。不过看官方文档的介绍,给人感觉借鉴了不少RTCP/RTP的协议特点。不晓得有没有拿了一些RTSP,毕竟三者是可以放在一起做组合的。
在看x264代码的时候,总是会看到sad、satd、subpixel。
至于sub pixel这个单词还算比较直观,子像素。当时脑补中的理解是,相邻像素按照不同权重计算出来的一种抽象像素,类似插值像素一样。
后来简单查了一下,才知道这玩意是亚像素。
即像素是感光器件上的实际一个像素点,对于亚像素就是感光器件上像素之间的抽象点。网上说是为了提高器件分辨率的一种抽象,但具体上我也没有实际有多少理解。
疯狂加班快4个月,资本家坚持走国际一线的12小时6天的工作强度。
最近在反思一个加班这个事情的好与坏,在若干年前,我并不抵制加班,觉得加班还能给我带来一些收获。因为那时候我还有很多东西不懂,需要学习。
现在不同了,并不是我不需要学习了;而是在反思加班是不是成为一种疲劳战的无意义行为。
首先说一下引发,我这种想法的主要原因:
1,上班地点距离住处有20km+,每天往返需要不少于2小时
2,公司加班对我的吸引太小(没有工资、没有利益、也没有任何有意义的学习收获)
3,资本家纯粹为了压缩成本和排挤人员的一种手段而已。
先看一看现在一些所谓的“大公司”是如何通过诱人的“条件”来吸引员工加班:
1,年终奖(小命在人家手里,呵呵~~~当然还有其他类似的手段)
2,营造“轻松的”气氛(有免费咖啡、有免费晚餐、有娱乐或健身场所)
3,kpi(请参考某厂)
4,虚荣心(各种莫名其妙的头衔,让员工增加对公司的认同感)
5,引入人为的竞争机制
6,企业联盟,形成圈内加班文化
7,其他(各种培训,各种活动;这些是一种调节)
最近头发掉的有点多了,整个人状态也有点不对劲了,不再像之前那样学习和工作效率那么高了。除了一些工作上分工的变化(精力分散),还有就是疲劳战。
目前所待的一家公司是一个小公司,行业前景不错,但老板过于强势以及心心胸狭隘;目前公司虽然走在相对高速发展的路上,但未来很有可能要出大事。
老板为了节约成本,倒逼研发体系能够快速的完成他自己认为的一些所谓的“优秀需求”,提出了加班这个要求。
事实上,加班要加的有效也是一个很难的事情。出工不出力,出力不出正常的力,也是我所遇到的加班情况中比较常见的几种现象。
当宣布进行加班的那天开始,我就在想加班的时候要做点什么好呢?
1,写工作上的代码?
2,看书?
3,娱乐?
4,果断不加班?
首先我否决掉的是1,3,4。原因有几点,老板是做销售出生的人,不懂技术。而做销售出生的人,往往有一种特点,就是急功近利。
情商高的销售,能力强的销售,是解决问题;情商低的销售,能力低的销售,则是为了赚钱不顾一切!从老板强制加班,且不做任何铺垫或者有意义的准备工作上来看,老板应该属于比后者稍强,比前者较弱的一个人。
至于娱乐和不加班,基本不太可能,主要是公司没有提供任何娱乐场所,另外就是除了想跑里,还是只能乖乖的呆在这里熬时间!
因此,我就开始了我的看书计划;一周6天,拿5天来看书,但实际上只有4天在看书。
差不多也看了快半年的书,差不多也快看完2本900多页有一定难度的技术类书籍。直到今天开始,才发现看书效率正在下降,接受和学习能力正在逐渐变弱。
反思得知:
1,疲劳了
2,迷茫了
3,没有当初那么有激情了
4,吸引我的事情正在逐渐淡化了。
就从我本人的性格来看,实际上,只要是不是累的快不行,一般情况下1不会成为主要的问题。就目前来说,更多的还是4和2。所谓身体上的疼痛(腰背疼痛),主要是还是由于情绪所带来的放大或者突出而已。实际上, 现在的人谁身上没几个毛病?
所以今天特意抽个时间,出来反思一下,加班到底有没有用,要不要做出一些改变来。
1,检查变量是否被改写
通过变量前后各插入一个字长的缓冲带(32bit的字长是4byte,64bit的字长是8byte),并且这个缓冲区均用0xCC填充(即 汇编指令的int 3)。
检查时机1:当对变量进行访问时,会检查这两个缓冲带。
检查时机2:函数返回时,进行栈检查。
只要缓冲带有任何一个字节不是0xCC,那就是变量被改写了。
2,char buff[100]溢出
首先按照普通变量的方式,在这个buff首位加上一段缓冲区(缓冲区具体大小由编译器决定),接着还是用0xCC填充。
并对这个buff的地址、大小、变量名,插入到一个错误检查链表。在函数返回时,会对这个链表进行检查。主要检查的还是这个buff的两侧缓冲带是否均被0xCC填充。
3,栈指针(EBP),栈顶(ESP)
有几种方式会导致EBP和ESP被改写:
第一种:如果通过溢出攻击的方式,会函数返回时的返回地址在栈上被改写。这就可能间接导致栈在函数进入前和退出后的关键状态不一致(EBP、ESP、前一栈帧的函数返回地址不正确等)。
第二种:栈出现与其增长的反方向溢出时,如栈是向上增长的,如果出现下溢时,可能会出现EBP指向的栈空间内容被改写,进而导致函数返回时ESP和EBP之前存储值不一致。
因此需要做一个安全cookie,这个cookie本质是一个随机数和ebp异或得到的。当要进行校验时,再异或一次就可以得到原先的ebp的值。
在vc8里面cookie有两个,一个是esp或ebp 和 随机数 异或得到的,另一个是 esp或ebp 和随机数的取反异或得到的。
4,对esp的针对性检查
函数返回时和ebp指向的帧地址进行比较。
1,数据结构回顾,找本靠谱的,然后实现一把例子啥的。
2,高数回顾,公式跟着推导一把
3,找本能看懂的离散书,主要看公式推导这块
4,1、2和3都已经ok了以后,看算法导论。
最近在学opengl,在看一个例子中。opengl的只有60fps,感觉到很好奇。
无意见发现显示器的刷新速度也是60hz。修改了显示器的刷新速度为75hz以后,opengl渲染的那个范例也提高到了75fps。
可见opengl默认情况下最大刷新速度与当前屏幕的刷新速度一致。
也就是说,如果运行一个非全屏游戏时,设定的设定的刷新速度为60hz,那么整个游戏的最大fps就为60hz。
得到的结论:最大刷新速度不超过当前显示屏幕设定的设定刷新速度。不知道对于全屏游戏来说是怎样的?
我们公司有这个一段代码,后来看了高效c++之后就总感觉有问题。不试不知道,一试全是地雷阵。
一般会写这么一个函数,返回的是引用。这样也符合C++里面的一些思想。但如果这样的函数没有用好的话,留下的就是一个地雷
std::vector<int>& Return_null_reference()
{
.....
}
例如有如下代码
std::vector<int>& Return_null_reference()
{
std::vector<int> *pTmp = NULL;
return *pTmp;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
std::vector<int> *pTmp1 = NULL;
pTmp1 = &Return_null_reference();
std::vector<int> &pTmp2 = Return_null_reference();
Sleep(1);
}
我在vs 2008 sp1中编译不但能够通过,而且不会报错。执行的结果就是,ptmp1指向了一个空指针,ptmp2引用了一个空指针。
这里实际上看上去ptmp2会有问题,因为在引用的变量定义时,需要在编译器就要确定引用的对象是一个非NULL地址。但事实上这里因为引用了一个函数的返回,由于函数的返回值是属于运行时问题,所以编译器不做检查。于是就留下了一个坑。
高效C++中说过,不要随便引用一个指针指向的对象,因为有可能那个指针是指向NULL。
同时也隐约讲过引用不的不当反而比指针会更危险。
要利用编译器检查引用非NULL的特性,需要显示的指明被引用的对象是编译时就可以确定内存地址的。
之前简单看过一点c++11的特性,里面讲了一堆左值和右值。说来说去有一部分还是在谈论关于临时变量的问题。
目前有这么一个函数:
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
Rational result(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
return result;
}
上面这个函数在调用的时候因为返回的是局部变量,因此返回的时候编译器会插入代码会产生一个临时变量,然后将result拷贝到临时变量中返回出去。但让这里谈论的前提是,一些编译器的优化关掉。
而对于下面的代码来说编译器的行为就会不一样。因为这段代码已经显式的告诉编译器,这个这里会构建一个匿名的临时变量并返回,因此编译器在这里不会再次构建临时变量,而是直接将代码中创建的匿名对象直接返回出去给外面。这样做可以节约一个对象的创建和销毁时间复杂度。
const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
}
那个过chromium上的source tarball解压以后,在执行了gclient sync之后,在电脑A上面编译chrome工程ok。
然后执行clean,删除 build/debug下的所有文件,打压缩包。
保存到另一个电脑B上时,出现一大堆编译问题。
chromium的代码与编译脚本的生成太复杂,以至于有时候很难搞清楚到底要保留哪一些,要剔除哪一些。
现在想独立把chromium的代码拿下来然后做一个分支,发现太困难了。都搞了整个十一了,还没弄好,无奈至极!打算放弃!sh!t
以前我用的是网通对称10M,刚开始用的时候就发现路由力不从心,常常都是带宽还没有跑满。
后来发现10M的利用率越来越少,到期后就改成了4M。下面是我对我所在地网通的几个认识。
readmore
今天有空来整理了一下数据库。我偶然在数据库看到大学时期的博文。
回头看了一下,发现真是一个喜欢抱怨的小鬼。然后就开始逐条逐条的删起来了。
按理说这是我青春的印记,应该留下来以后没事的事情可以拿来回忆一下。
看着当时的博文,明显能够感受到曾经的无忧无虑和百无聊赖。这种生活相信是很多踏入社会后的人,可遇而不可求的。
首先依据网上的说法,到C:\Windows\Resources\Ease of Access Themes下找是找不到standard配色方案的,这原因我也不清楚。只能说假专家比假货还多。
我检查事件记录器的时候发现,我的色深不对,是16位的。所以没有办法启动桌面窗口管理器。
修改成32位,再去看配色设置,可以见到有standard了
有一些程序在写好了以后需要做修改,但是由于源代码缺失。
并且修改点可能很简单,也就是修改某一个函数的跳转地址之类的。直接用ollydbg修改即可。但前提是要知道指令的地址,以及要修改到的位置。
对于win api就很简单了,直接通过加载模块的地址一查询,就可以跳转到对应的反汇编地址上。
但对于内部自己做的一些函数,那就需要做汇编代码的分析了。
有某种数据类型需要满足如下需求:
1,单一线程内部使用
2,生命周期与线程一致
3,便于管理
一般的做法如下:
unsigned int ThreadMain(LPVOID p)
{
unsigned int g_ThreadVar = 0; //这个作为线程自身的共享变量
...
return 0;
}
这样做的坏处,主要是在代码里面可维护性和可管理性变差了。
所以就干脆采取tls来进行管理
unsigned int ThreadMain(LPVOID p)
{
unsigned int* var1 = new unsigned int;
tlsset(id, var)
...
return 0;
}
第一次在火车官网上订火车表。
本来打算订一张20号到南京的火车票。由于订的车子是凌晨开车,时间算错了,倒是订票时下单的时间比计划出行时间早了一天。刚才准备上车时被列车员发现,没上成车又灰溜溜的去购票厅看了一下,凌晨是没有希望了。所以打道回府又花了好多钱。
订票时没有注意,确实是自己的错。但话又说回来,乘车人没有上车,铁路部门没有电话咨询,这一点确实做得不好。花了100多大洋送了铁老大。算是又一次在铁老大的霸气上吃了一亏。
出门比较衰。还没有出门就无缘无故的花了,好几百。真是一个不好的开始,不过也罢。摆正心态。睡一觉,明天起来去做汽车。发现还是汽车性价比最高。坐着是否舒服就不知道了。