websocket协议rfc阅读散记

websocket协议(rfc6455)见此地址: tools.ietf.org/html/rfc6455
记录几个觉得比较有意思的点如下:

1、双工通信
双工通过把数据切为多个frame实现;
数据收完了回去的时候带上自己想发的数据。

2、Control frame
Control frame可以插在Data frame之间发送,标准要求接收方优先处理Control frame;
Control frame只包括三个:Close、Ping、Pong。

3、可以主动发pong
在对面没有发ping的时候,可以主动声明自己依然存活。

4、Mask
每个frame中必须包含一个key,payload必须用这个key做mask。
每个frame的key必须不相同且无法预测;
Server端响应时,必须不做mask。
(标准中提到这样设计是安全考虑。
主要是防止cache污染攻击:
攻击者用一对自己控制的Server和Client,通过伪造origin/host和响应的方式达到污染cache的目的。
这个设计主要是为网络上现存的很多实现不完善的无法分辨websocket协议的HTTP设施而考虑。)

5、防syn flood
同样2个的host和port之间,不允许并发两个CONNECTING(正在连接)状态;
但允许多个连接同时存在,比如浏览器开了多个Tab的情况;
标准中说这个设计是为了防止syn flood类的攻击。确实,如果没有建立连接就直接拒绝后续的syn的话,的确可以达到一定的防守效果。

6、断线重连
意外关闭后重连时,每次重试的间隔时间交由客户端决定。
建议随着重试失败次数增加,间隔越来越长。

7、扩展支持
协议设计中支持用户在协议的同一层扩展协议:
a>有extension字段供用户声明自己的协议;
b>在opcode、playload data等多个地方留下了自定义空间;
c>留下了status code 3000-3999用于公有扩展,status code 4000-4999用于私有扩展(不许注册)。
(但貌似无法改变1对1的传输结构)

8、平台限制
记得要遵守平台的限制,比如说不要被一个超级大frame撑爆内存。

9、身份认证
websocket不提供任何身份认证机制,但可以使用HTTP的basic auth、TLS认证或者基于cookies的方式;

10、安全传输
一个是origin头的机制。
传输加密通过TLS实现;

11、错误处理
任何非法数据都应该直接导致断开TCP连接。如果是在握手阶段收到的非法数据,可以回一个合适的HTTP response。

12、opcode列表

     |Opcode  | Meaning                             | Reference |
    -+--------+-------------------------------------+-----------|
     | 0      | Continuation Frame                  | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 1      | Text Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 2      | Binary Frame                        | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 8      | Connection Close Frame              | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 9      | Ping Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 10     | Pong Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|

13、URI的样子

 ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
 wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]

14、frame结构

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

15、另外学了一个之前漏掉的关于HTTP的小知识
Ergo, the following are
equivalent:

Sec-WebSocket-Extensions: foo
Sec-WebSocket-Extensions: bar; baz=2

is exactly equivalent to

Sec-WebSocket-Extensions: foo, bar; baz=2

《星际穿越》观后感

1.
电影一开始写的那个女儿太招人爱了。
弄得我也很想有一个这样的。

悲剧就是把美好的东西毁灭给人看嘛。
结果到后面分离的时候就很伤心。
最后人鬼两隔的时候,那更是瞬间引爆泪点。
有点人鬼情未了的意思。再加上父亲本来也就是那个“GHOST”。
一下子伏笔出来,眼泪就忍不住了。

2.
还有那个儿子。开始没感觉。
后来到了老婆还是孩子咳得不行还不肯离开屋子的时候,我才明白。
他儿子是另外的一种表达方式
他其实就和大多数,看到地球不行了,但依然不想离开地球的人一样。
眷恋着这个地球(也是历史和回忆,也是情感)不需要原因,也说不清楚原因,是他们的缩影。
当然也是我们的缩影。

3.
所以这一对儿女,简直完美。
一个种地,一个探索太空。
一个极富情感,一个极富理性。
但情感的这位,在能去空间站的时候也去了空间站,可以被说服。
且理性的这位,也能从她对父亲的情感中得到灵感,可以被打动。
这两个父亲分别的两面,一个种着粮食争取着时间,另一个玩命探索和纠结探寻最终解。
最终共同拯救了人类。
他们虽然也争吵,但这是一个TEAM啊。
完美的TEAM,包括争吵都那么完美。

4.
简直是个创世纪的故事。
西方神话里面喜欢这样写,一个神的两面分化出两个人,然后这两个人balabala大一堆。
这其实就是这么个故事啊
最后创造了新的世界。

5.
这片子很有余味。
最终人类还是没有找到最终的栖息地,总不能一直在土星轨道上活着,人口没办法大规模扩张。
最终的栖息地是那个失去恋人的美女找到的那个星球。
人类还是要去找到她,才能真正释放人口。
这中间肯定又一大堆艰难险阻。
而且定居了之后还指不定发生什么,地球还有地震和海啸呢。住久一点说不定那星球也有什么硬伤没被发现,搞不好又要迁移。
永远的征途,永远的星辰大海。

6.
还有运维和开发的关系。
主角是个优秀的运维,负责操作。
那些科学家是开发,了解一大堆细节。
操作也能玩很多花,且胆子必须大。
而且绝对依赖自己的经验,且不是什么公式。
比如说在那个水的星球降落的时候就很典型。
机器人告诉他:不行,现在速度太快了。(明显是开发的思维:阈值太高,超过了保险值)
他的回答是什么?
他回答:NO,我唯一一次出事就是减速造成的(没那么多道理,我依赖的是我的经验。我玩的不是保险区间,我玩的就是刀口上舔血,在紧急时刻如何突破保险区间最大化发挥性能解决临时问题就是韵味能做而你开发做不到的。)
其实这里更像是OP

7.
还有那首诗也很有味道,不要温和的走进那个良夜。
用词晦涩本来是个坏事,这个诗单独看有点扯,生造词“良夜”。
但是在这个语境下,“良夜”就很有味道了。。
翻译的好。

8.
还有一个打动我的地方,那个父亲说:
“我们是开拓者创造者,而不是什么守护者。”
和我的想法一样……
他开始的那种无奈,我有一点能感受到。
所以后来他能实现自我,我就特别感动。

满意度面谈

只是想问问你最近怎样。
工作的满意度如何?
你的满意对我们来说很重要。

我想知道,你喜欢这样的工作吗?
能保持工作生活的平衡吗?
这个工作对你来说还有挑战吗?
怎样更具挑战呢?
你能给我一个例子吗?

关于工作的部分,
还有什么事是我应该做但还没有做的呢?或者是其它同事。

谢谢你的坦率直言,你要是不说的话,我们自己都不知道这些情况。
我希望你知道你做得很好,你对我们TEAM很重要。

phantomjs抓取ajax页面一例

# file: example.coffee
# usage: phantomjs example.coffee
page = require('webpage').create()

console.log 'The default user agent is ' + page.settings.userAgent

page.settings.userAgent = 'Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53'
page.open 'http://www.sina.com.cn/', (status) ->
  if status isnt 'success'
    console.log 'Unable to access network'
  else
    console.log page.content

phantom.exit()

安卓备忘八则

Android Studio中替换图片资源不起作用

删除目录~/AndroidStudioProjects/www/app/build/intermediates/res

Android Studio中导入jar

1、cp jar到~/AndroidStudioProjects/www/app/libs;
2、在libs文件夹中jar文件下鼠标右键,单击菜单 add as library;

设置app版本号

versionCode是真的版本号;
versionName是用户看到的版本号;

1、Eclispe中:
文件src/main/AndroidMainfest.xml里:
package="com.wirelessqa.sqlite"
android:versionCode="1"
android:versionName="1.0">

2、Android Studio中:
文件src/build.gradle里:
defaultConfig {
applicationId “com.hanguomv.www”
minSdkVersion 15
targetSdkVersion 20
versionCode 1
versionName “1.0”
}

Android Studio打包apk时出现missTranslation

文件res/values/*xml里加上
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation" >

java.io.FileNotFoundException

connection.setDoInput(true);
connection.setDoOutput(true);

这两个设置会导致HTTP使用POST方法,即使明示

connection.setRequestMethod(“GET”);

也无效。

进而导致java.io.FileNotFoundException at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStrea。

去掉这两个设置就可以正确访问了。

未覆盖 java.util.logging.Handler 中的抽象方法

错误现象:
Error:(36, 45) <匿名 com.hanguomv.www.index$1> 不是抽象的,并且未覆盖 java.util.logging.Handler 中的抽象方法publish(java.util.logging.LogRecord)

错误原因:
自动import系统错将java.util.logging.Handler包import进来了;

解决方法:
手动去掉import java.util.logging.Handler;
手动加上import android.os.Handler;

webview旋转不刷新、Activity旋转不重启

参见官方文档:

http://developer.android.com/guide/topics/manifest/activity-element.html

网上的解决方案大多是:
android:configChanges=”orientation|keyboardhidden”
这在android:minSdkVersion和android:targetSdkVersion等于13之前是ok的。

目前,这样设置才行:
android:configChanges=”orientation|screenSize”

去掉TextView之间的空白

有时margin、padding啥的设置为0是没有用的,这时就直接搞成负数就好了……
如:
android:layout_marginBottom=”-5dp”

rails4发布production版备忘

1、编译css和js

执行

  RAILS_ENV=production rake assets:precompile

如果出现错误

  did not recognize your adapter specification

如果multi_json不是版本1.7.9这个有问题的版本,则在Gemfile中增加

  gem 'yajl-ruby', :require => "yajl"

2、设置环境变量

export HANGUOMV_DATABASE_PASSWORD=xxxxx
export SECRET_KEY_BASE=xxxxx

3、初始化production的数据库

RAILS_ENV=productionrake db:create
RAILS_ENV=productionrake db:migrate

4、启动production的thin

rails s -p 3100 -b 127.0.0.1 -e production -P /var/www/rails/site/tmp/pids/server3100.pid -d
rails s -p 3101 -b 127.0.0.1 -e production -P /var/www/rails/site/tmp/pids/server3101.pid -d

5、配置httpd服务

<VirtualHost *:80>
    ServerName www.site.com
    DocumentRoot /var/www/rails/site/public
    ErrorLog logs/www.site.com-error_log
    CustomLog logs/www.site.com-access_log common

    ProxyRequests Off
    <Proxy balancer://site>
        BalancerMember http://127.0.0.1:3100
        BalancerMember http://127.0.0.1:3101
    </Proxy>
    ProxyPass /assets !
    ProxyPass /robots.txt !
    ProxyPass /favicon.ico !
    #ProxyPass / http://127.0.0.1:3100/ connectiontimeout=5 timeout=30
    ProxyPass / balancer://site/
    ProxyPassReverse / balancer://site/
</VirtualHost>

6、启动服务

systemctl restart httpd

7、设置自启动

在/etc/rc.local中添加

cd /var/www/rails/hanguomv && SECRET_KEY_BASE=xxx rails s -p 3100 -b 127.0.0.1 -e production -P /var/www/rails/site/tmp/pids/server3100.pid -d && cd /root
cd /var/www/rails/hanguomv && SECRET_KEY_BASE=xxx rails s -p 3101 -b 127.0.0.1 -e production -P /var/www/rails/site/tmp/pids/server3101.pid -d && cd /root

rails4搭站备忘

1、安装系统依赖

yum install rubygem
yum install ruby-devel
yum install gcc
yum install nodejs
yum install v8
yum install httpd*
yum groupinstall "Development Tools"

gem install postgresql --no-ri --no-rdoc
gem install rake --no-ri --no-rdoc
gem install rails --no-ri --no-rdoc

2、配置httpd

vim /etc/httpd/conf.d/vhosts.conf增加如下内容
<VirtualHost *:80>
    ServerName www.site.com
    ProxyPass / http://127.0.0.1:3000/ connectiontimeout=5 timeout=30
    ErrorLog logs/error_log
    CustomLog logs/access_log common
</VirtualHost>

systemctl start httpd

3、初始化postgresql

su - postgres
createuser sitedbuser
psql
\password sitedbuser
ALTER ROLE "sitedbuser" CREATEDB;

详见CentOS7下初始化PostgreSQL

4、创建站点

rails new site --database=postgresql
cd site

5、配置数据库连接

vim config/database.yml增加以下
  default: &default
  adapter: postgresql
  pool: 5
  host: 127.0.0.1
  port: 5432
  username: sitedbuser
  password: passwd

执行rake db:create

6、配置gem

vim Gemfile增加以下
  gem 'less-rails'
  gem 'therubyracer'
  gem 'twitter-bootstrap-rails'
  gem 'devise'
  gem 'thin'

执行bundle install

7、初始化bootstrap和devise

devise是权限控制插件。

rails g bootstrap:install
rails g devise:install
rails g devise:views
vim app/views/layouts/application.html.erb增加
  <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>
  <%= yield %>

rails g devise User

如果想往用户表里面加字段则vim  db/migrate/*_devise_create_users.rb,默认不加就不用了。

rake db:migrate

8、汉化devise

cp config/locales/devise.en.yml config/locales/devise.zh.yml,汉化之
vim app/views/devise/sessions/new.html.erb,汉化之
vim app/views/devise/registrations/new.html.erb,汉化之

9、创建一个页面

创建一个控制器:rails g controller welcome index

在config/routes.rb里增加默认路由:root 'welcome#index'

给页面增加权限控制,vim app/controllers/welcome_controller.rb增加一行:
  before_filter :authenticate_user!

10、启动站点,然后创建更多MVC

rails s -p 3000 -b 127.0.0.1 -d
...