搭建WebRTC视频会议服务01

本系列主要是描述了,在虚拟机中通过CentOS7+Intel Collaboration Suite4.1实现WebRTC视频的基本步骤。

1、安装CentOS7,并配置网络信息
A、通过网卡1(HostOnly),实现主机与虚拟机的通讯
B、通过网卡2(NAT),实现虚拟机的外网访问

2、下载Intel Collaboration Suite4.1,并解压,将需要的组件上传到虚拟机
https://software.intel.com/en-us/webrtc-sdk

3、安装中间件
3.1、Node.js
https://nodejs.org/dist/8.12.0/

#官方文档上要的版本为node-v6.9.5-linux-x64,但实际要求v8以上
tar -xf node-v8.12.0-linux-x64.tar.gz
mv node-v8.12.0-linux-x64 /home/neohope/
ln -s /home/neohope/webrtc/node-v8.12.0-linux-x64/bin/node /usr/bin/node
ln -s /home/neohope/webrtc/node-v8.12.0-linux-x64/bin/npm /usr/bin/npm

3.2、Erlang
https://bintray.com/rabbitmq/rpm/erlang/19.3.6.11-2

#前两步骤主要是为了偷懒,安装依赖包
yum install erlang
yum erase erlang-erts
rpm -ivh erlang-19.3.6.11-2.el7.centos.x86_64.rpm

3.3、Rabbitmq
http://www.rabbitmq.com/download.html

#注意Erlang版本依赖
rpm -ivh erlang-19.3.6.11-2.el7.centos.x86_64.rpm
#配置为自动启动
chkconfig rabbitmq-server on
#开启服务
service rabbitmq-server start

3.4、MongoDB
http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/RPMS/

#官方要的mongodb版本很低
rpm -ivh mongo-10gen-2.4.9-mongodb_1.x86_64.rpm
rpm -ivh mongo-10gen-server-2.4.9-mongodb_1.x86_64.rpm

4、安装Peer Server
4.1、安装

tar –zxvf CS_WebRTC_Conference_Server_Peer.v4.1.tgz
mv PeerServer-Release-4.1 /home/neohope/
cd /home/neohope/PeerServer-Release-4.1
npm install

4.2、测试

cd /home/neohope/PeerServer-Release-4.1
node peerserver.js
#测试完毕后ctrl+c退出

《硅谷来信》摘录

最近听完了吴军博士的《硅谷来信》,收获不少,将部分内容摘录于此:

1、专业人员要适当了解大局,管理者要注重细节

2、引擎和刹车
引擎应该是自下而上的,公司才会有源源不断的动力。
高层要想办法调动基层的动力,而不是在后面催促大家前进。高层要做的事情是,在适时的时候刹车。

3、五级工程师划分
第五级:能独立解决问题,完成工程工作;
第四级:能指导和带领其他人一同完成更有影响力的工作;
第三级:能独立设计和实现产品,并且在市场上获得成功;
第二级:能设计和实现别人不能做出的产品,也就是说他的作用很难取代;
第一级:开创一个产业。

4、努力和天分的关系
从0到50靠经验;
从50到90靠努力;
从90到100靠天份。

5、确认公司价值观和企业文化
技术和产品稳定性,工程师文化,谷歌
用户体验,产品经理文化,腾讯,苹果,Facebook
销售业绩,结果导向,销售文化,阿里与亚马逊

6、不同人员用不同管理方式
能力低,积极性高,新人居多,给予培训带教和指导,引导和培养
能力低,积极性低,PIP计划
能力高,积极性高,给予新的挑战,防止倦怠,给予机会,给予培训
能力高,积极性低,调整岗位,给予许诺,调整态度

新员工,bootcamp计划,新兵训练营
待提升员工,pip(performance improvement plan)计划,能力提升计划
A、加强实践管理,严格考勤
B、制定周计划,并严格执行
C、一对一专业指导
D、给予介绍自己工作的机会

7、招合适的人
主要看:人品、能力、主动性
一个原则:录用的人,高于目前平均水平

8、工作时阻碍进步的常见问题
A、工作和职业要分清
B、不做工作的主人
C、被语言暴力激怒
D、疏于沟通

一种U盘蠕虫的攻击方法

最近,从做安全的哥们那里,听说了一种利用社会工程方法,实施蠕虫攻击的案例。具体攻击是这样实施的:

攻击者要攻击一个内外网隔离的实验室,但一直无法攻入内部网络。

于是,他们精心设计了一种U盘蠕虫,将蠕虫伪装为容易引发人好奇心的资料“比如小电影”,与其他无关资料一起,拷贝到几个各异的U盘中。

然后故意将U盘散布到实验室工作人员的上班路径中。

然后总有一两个眼神比较好,好奇心比较重的工作人员,点击了伪装的蠕虫(U盘策略为,能进不能出)。

还好他们的其他防护策略做的比较好,最终没有引发严重的问题,但触发了安全警报。

于是开始排查,但投U盘的人都比较贼,而且U盘很小,没能找到。据说最终收缴上来的U盘有好几个。

然后,实验室进一步升级了安全措施,并禁用了U盘的读取权限。

在同步排查外网的时候,才发现,几个月前外网就被人攻破了。

然后又花了大价钱,升级的外网安全防护。

人性的好奇心、贪婪和不够警惕的友善,永远是社会工程攻击的重要途经。

SQL Server连接占线

使用ADO及ODBC连接SQL Server时,如果连接没有处理好,很容易出现下面的错误:

[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt.
连接占线导致另一个hstmt。

[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another command.
连接占线导致另一个命令。

产生这个错误的原因是,在同一个connection中,同时操作了多个数据集。

解决这个问题有两个方法
1、不要在一个connection中,同时打开多个数据集
2、在SQL SERVER2005以上版本,可以使用MARS (Multiple Active ResultSet)。在连接字符串中加上”Mars_Connection=yes;”就可以支持多数据集了。

关于MARS,可以参考这个:
http://msdn2.microsoft.com/en-us/library/ms345109.aspx

浅谈CPP智能指针

智能指针其实并不是指针,而是一个特殊对象。
在智能指针对象生命期即将结束时,它会调用析构函数释放有它管理的堆内存。
访问智能指针管理对象的方法,使用操作符“->”(重载)。
访问智能指针本来的方法,使用操作符“.”。

我们常见的智能指针有以下几种:

C98
std::auto_ptr
第一代智能指针,有些操作比如“=”坑比较多,不推荐使用。

C11
std::unique_ptr
独占对象,并保证指针所指对象生命周期与其一致。

std::shared_ptr
可共享指针对象,可以赋值给shared_ptr或weak_ptr。
通过引用计数的方式控制生命周期,当指针所指对象的所有的shared_ptr生命周期结束时(引用计数为0时)会被销毁。

std::weak_ptr
可以指向shared_ptr,但并不影响引用计数。
不影像所指对象的生命周期,在引用所指对象时,先用需要lock()才能使用。

Boost
不共享对象,类似于std::unique_ptr
boost::scoped_ptr
boost::scoped_array

共享对象,类似于std::shared_ptr
boost::shared_ptr
boost::shared_array

共享对象,但不改变对象引用计数,类似于std::weak_ptr
boost::weak_ptr

侵入式引用计数,要求使用对象自己实现计数功能
boost::intrusive_ptr

下面给一个例子,说明一下std下的四种智能指针。
1、SmartPointerTest.cpp

#include <memory>
#include <iostream>
#include "MyTest.h"

using namespace std;

void test_auto_ptr()
{
	std::auto_ptr<MyTest> auto_ptr_01(new MyTest("tom", 20));

	if (auto_ptr_01.get())
	{
		auto_ptr_01->sayHello();
		auto_ptr_01.get()->_name = "jerry";
		auto_ptr_01->sayHello();
		(*auto_ptr_01)._age += 1;
		auto_ptr_01->sayHello();
	}
	
	//auto_ptr_02会抢占auto_ptr_01的对象
	//此后auto_ptr_01不指向MyTest对象
	std::auto_ptr<MyTest> auto_ptr_02 = auto_ptr_01;
	if (auto_ptr_01.get())
	{
		cout << "auto_ptr_01 is released" << endl;
	}
	auto_ptr_02->sayHello();

	//只是释放所有权,并不释放内存
	//MyTest* test = auto_ptr_02.release();

	//释放内存
	auto_ptr_02.reset();
	if (!auto_ptr_01.get())
	{
		cout <<"auto_ptr_02 is released"<< endl;
	}
	
}

void test_unique_ptr()
{
	//独占对象
	//保证指针所指对象生命周期与其一致
	unique_ptr<MyTest> unique_ptr_01(new MyTest("tom", 20));
	unique_ptr_01->sayHello();

	//不允许直接做右值
	//unique_ptr<int> unique_ptr_02 = unique_ptr_01;

	//需要通过move来处理
	unique_ptr<MyTest> unique_ptr_03 = move(unique_ptr_01);
	if (!unique_ptr_01)cout << "unique_ptr_01 is empty" << endl;
	unique_ptr_03->sayHello();

	//释放指针
	unique_ptr_03.reset();
	if (!unique_ptr_03)cout << "unique_ptr_03 is empty" << endl;
}

void test_shared_ptr()
{
	shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20));
	shared_ptr<MyTest> shared_ptr_02 = shared_ptr_01;
	shared_ptr_01->sayHello();
	shared_ptr_02->sayHello();

	shared_ptr_01.reset();
	if (!shared_ptr_01)cout << "shared_ptr_01 is empty" << endl;
	shared_ptr_02->sayHello();

	shared_ptr_02.reset();
	if (!shared_ptr_02)cout << "shared_ptr_02 is empty" << endl;
}

void test_weak_ptr()
{
	shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20));
	weak_ptr<MyTest> weak_ptr_01 = shared_ptr_01;
	shared_ptr_01->sayHello();
	weak_ptr_01.lock()->sayHello();

	weak_ptr_01.reset();
	if (!weak_ptr_01.lock())cout << "weak_ptr_01 is empty" << endl;
	shared_ptr_01->sayHello();
	
	weak_ptr<MyTest> weak_ptr_02 = shared_ptr_01;
	weak_ptr<MyTest> weak_ptr_03 = weak_ptr_02;
	if(weak_ptr_01.lock())weak_ptr_02.lock()->sayHello();
	shared_ptr_01.reset();
	if (!weak_ptr_01.lock())cout << "weak_ptr_02 is empty" << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	test_auto_ptr();
	test_unique_ptr();
	test_shared_ptr();
	test_weak_ptr();

	return 0;
}

2、MyTest.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class MyTest
{
public:
	MyTest(string name, int age);
	~MyTest();
	void sayHello();

public:
	string _name;
	int _age;
};

3、MyTest.cpp

#include "stdafx.h"
#include "MyTest.h"

MyTest::MyTest(string name, int age)
{
	_name = name;
	_age = age;
}

MyTest::~MyTest()
{
}

void MyTest::sayHello()
{
	cout << "Hello " << _name<< "! You are "<< _age <<" years old." << endl;
}

PS:
聪明的你有没有发下,CPP的智能指针,与JVM内存中的四种引用方式,强引用、软引用、弱引用,虚引用,有很多相似的地方呢?

编译ss-qt5

1、安装依赖

sudo apt-get install qt5-default
sudo apt-get install cmake
sudo apt-get install libbotan-2-dev
sudo apt-get install libqrencode-dev
sudo apt-get install libzbar-dev

2、编译libQtShadowsocks

wget https://github.com/shadowsocks/libQtShadowsocks/archive/v2.1.0.tar.gz
tar -xvf libQtShadowsocks-2.1.0.tar.gz
cd libQtShadowsocks-2.1.0
make build
cd build
cmake .. -DCMAKE_INATALL_PREFIX=/usr -DUSE_BOTAN2=ON
make -j4
make
sudo make install

3、编译shadowsocks-qt5

git clone https://github.com/shadowsocks/shadowsocks-qt5.git
cd shadowsocks-qt5
make build
cd build
cmake .. -DCMAKE_INATALL_PREFIX=/usr
make -j4
make

4、运行

ss-qt5

SonarQube集成代码覆盖率

Java项目

#清理,并构建
mvn clean install javadoc:aggregate -Dadditionalparam=-Xdoclint:none surefire-report:report -Daggregate=true

#sonar收集信息
mvn sonar:sonar -Dsonar.host.url=http://127.0.0.1:9000 -Dsonar.scm.disabled=True -Dsonar.junit.reportPaths=target/surefire

.Net项目

#准备收集信息
MSBuild.SonarQube.Runner.exe begin /k:"MyProject" /n:"MyProject" /v:"1.0" /d:sonar.host.url=http://127.0.0.1:9000 /d:sonar.scm.disabled=True /d:sonar.cs.vstest.reportsPaths="%CD%\*.trx" /d:sonar.cs.vscoveragexml.reportsPaths="%CD%\MyProject.coverage.xml"

#清理并构建项目
msbuild MyProject /t:Clean /t:Rebuild

#进行单元测试并生成测试报告
"%VSINSTALLDIR%\Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe" collect /output:"%CD%\MyProject.coverage" /verbose "%VSINSTALLDIR%\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" /Logger:trx "MyProject\bin\Debug\MyProject.dll"

#报告转换为xml格式
"%VSINSTALLDIR%\Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe" analyze /output:"%CD%\MyProject.coverage.xml" "%CD%\MyProject.coverage"

#结束分析
MSBuild.SonarQube.Runner.exe end

jekyll环境搭建

大家都知道github pages是用了jekyll,我们自己如何搭建一个网站呢?

#安装依赖环境
apt-get install ruby ruby-dev

#安装jekyll
gem install bundler jekyll

#新建网站
jekyll new mysite

#开启网站
cd mysite
bundle exec jekyll serve --host 0.0.0.0

#浏览网站
http://172.16.172.80:4000

Boss与Leader

Boss Leader
驱动员工 指导员工
制造恐惧 制造热情
面对错误,喜欢使用人事惩罚手段 面对错误,喜欢寻找解决问题的技术或管理方法
只知道怎么做 展示怎么做
用人 发展人
从团队收割成绩 给予团队成绩
喜欢命令和控制 喜欢沟通和写作
喜欢说,“给我上” 喜欢说,“跟我上”

转自http://coolshell.cn/。