NodeJS和NW通过ffi调用dll/so动态库

0x01:使用的 npm 包

首先要安装 node-gyp, 用来重新编译依赖包。

1
npm instal -g node-gyp

然后主要用到下面三个包:

  • node-ffi – 使用Javascript调用动态库

  • ref – 用来定义数据类型,提供指针功能

  • ref-array – 用Buffer来实现C语言中的 array 数据类型

1
2
npm install ffi   //这个命令会同时安装上 refref-struct
npm instal ref-array

Read More

Mac安装memcached,解决Unable to initialize module 问题

使用Homebrew安装 memcached 服务端

1
2
brew search memcached
brew install memcached

使用Homebrew安装 php-memcached 扩展

1
2
brew install memcached
brew install homebrew/php/php56-memcached --build-from-source

启动并检查扩展是否正差

1
2
memcached -d -m 24 -p 11211
php -i | grep memcached

排查错误

如果php -i | grep memcached 并没有返回 memcached 的信息,那么打开php的错误log,
检查是否有这个warning

1
2
3
Warning: PHP Startup: memcache: Unable to initialize module
Module compiled with build ID=API20131226,NTS
PHP compiled with build ID=API20131226,NTS,debug

解决办法很简单, 是需要再安装扩展的时候跟上 --build-from-source 参数即可。

1
2
3
4
5
6
#先卸载
brew remove php56-memcached
rm -rf /usr/local/etc/php/5.6/conf.d/ext-memcached.ini

#再安装
brew install homebrew/php/php56-memcached --build-from-source

阿里云VPS搭建自己的的Hexo博客

1. 博客的架构

先搞明白Hexo博客从搭建到自动发布的架构,才能更好的理解我们每一步进行的操作。
不然只跟着步骤过了一遍,却不知道为什么这么做。

首先看这张架构图:
Hexo-Structure

整个流程就是本地将 *.md 渲染成静态文件,然后Git推送到服务器的repository,服务器再通过 git-hooks 同步网站根目录。

Read More

数据库及迁移规范

1. Migrations 起名规则

表名_动作_字段, 动作包括 create, add, delete ,alter。 这样起名的好处是,比较好查找一个表的改动。

如果改变了多个字段, 仅需要写其中一个字段的名称即可。

1
[table_name]_[action]_[column]

示例:

  1. 增加一个example_table 表,因为他没有影响字段,则命名为:

    1
    example_table_create
  2. example表中添加一个字段 user_name, 命名为:

    1
    example_table_add_user_name
  3. 修改 example_table 表中的 user_name , 命名为:

    1
    example_table_alter_user_name

Read More

Mac上安装Nginx+PHP5.6+MySQL+NodeJS+Express

1. 安装Homebrew

如果已经安装,请跳到下一步

HomebrewOSX 上注明的软件包管理器, 可以方便的安装很多常用软件。安装过程很简单,运行一下命令即可。

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安装完毕以后,由于Homebrew可以能会做一些编译的事情,所以需要安装command line tools, 我用的是 10.8.5 Mountain Lion,请在apple的开发者下载中心(https://developer.apple.com/downloads/)选择自己对应的版本进行下载安装。

brew(意为酿酒)的命名很有意思,全部都使用了酿酒过程中采用的材料/器具,名词对应以下的概念:

  • Formula(配方) 程序包定义,本质上是一个rb文件
  • Keg(桶)程序包的安装路径
  • Cellar(地窖)所有程序包(桶)的根目录
  • Tap(水龙头)程序包的源
  • Bottle (瓶子)编译打包好的程序包

最终编译安装完毕的程序就是一桶酿造好的酒, 更多内容请查看官方“酿酒文档”

Read More

产品狗刚入门时的容易犯错的小事

测试要点

  1. 登录注册功能,要加强力度测,测试非法注册,高频登录
  2. 网页的 Favicontitlekeywordsdescription
  3. 所有图片和链接的alttitile
  4. 输入框在没有输入和输入非法字符的测试
  5. 所有链接的正确性,保证跳转到正确的页面
  6. 设计到js组件的测试要考虑极限情况,比如轮播图最开始和最尾的事件响应

Read More

生活总是莫名其妙

生活真是各种起承转折,懒懒散散准备好入职资料,洗掉脏衣服迎接新工作的时候,被电话告知“您明天不用来了”。

脑子一瞬间放空,然后本能的不失逼格的回一句“明白,再见”。

这生活的幽默把我玩大了,来电时间是下午1:31,而我在1点的时候放弃了原本2:00的一个面试。

挂掉电话,喊不出来,只感觉压抑,一股绝望般的情绪夹杂着疲倦将我击蒙。感觉房间里忽然很灰暗,越是在黑暗中,越有对光的渴望。

我不能就这么放弃,拿好简历穿上衣服打的去。出租车上阳光这么好,风这么舒服,司机虽然走了远路,我想即使面试不成功,也当是散心了。

还好他们没有因为时间原因责备我,做完测试题,和平台经理的面试过程让我感觉一切都是天意。

Read More

等风来

一向文采翩翩的我好久不写东西,居然不知道从何说起

将《等风来》看了两遍,感觉自己很像程羽蒙,自诩不凡,想一直跑着冲着就能飞起来。

跑了好久,到不知道为什么跑的这么急,这么慌,怕跑慢了我就老了,就没法趁年轻疯狂了。

装着理想,还要看着房价,当自己疯着狂着度过这一年的时候,银行卡的数字总是很孤单。

知乎上看到一个问题,你什么时候感觉自己很穷。

前两天回烟台宿舍小party的时候有件小事忽然让我感觉自己很穷。

Read More

Git reset和revert的区别

两者的说明

  • git reset 重置
  • git revert 撤销

从字面上理解,重置是不管你做了多少次commit,一次性就撤回去了。

撤销的话,只能撤销某一次的commit

譬如,

commit-1, commit-2, commit-3, commit-4

运行 git reset --HARD HEAD~2

重置到倒数第三个状态 ,那么还剩

commit-1, commit-2

运行 git revert HEAD~2

撤销倒数第二个状态, ,就是删除 commit-2,那么还剩

commit-1,commit-3,commit-4

Read More

Socket.io握手和验证流程

Socket.io 支持两种方式的认证:

  1. 在初始化或者对话握手的时候进行全局的验证。
  2. 每个namespace下进行独立认证。

全局认证和namespace层的独立认证可以同时使用或者单独使用其中某一个。他们唯一的共同点是通用 handshakeData这个对象。 这个数据通过握手时发送的数据生成。所以如果想更好的了解怎么使用认证,首先要先理解握手过程。

握手

当客户端想和Socket.io服务器建立一个稳定的实时连接的时候,需要首先进行握手过程。握手过程通过一个XHR请求或者JSONP(跨域请求)请求进行初始化。

服务器收到连接请求时便会收集请求数据以便后来可能使用。这么做有两个原因:

  1. 用户可能想根据客户端的头信息(headers)或者IP地址进行认证。
  2. 不是所有的传输协议在与服务器建力实时连接的时候会发送头信息,所以我们内部的将握手信息存起来,确保用户在连接建立以后还可以使用这些数据。比如:你可能想在cookie headers里面读取session id,或者为一个连接初始化Express session

handshakeData对象包含以下信息:

1
2
3
4
5
6
7
8
9
10
{
headers: req.headers, // <Object> 请求的头信息
time: (new Date) +'', // <String> 连接的时间信息
address: socket.address(), // <Object> 远程的IP和端口对象
xdomain: !!headers.origin, // <Boolean> 是否是跨域请求
secure: socket.secure, // <Boolean> 是否是https加密协议
issued: +date, // <Number> 连接建立时的时间戳
url: request.url, // <String> 请求入口地址
query: data.query // <Object> URL参数对象(url.parse().query 的结果)或者空对象
}

address对象请参照 socket.address()

Read More