Websocket Protocol

下午用jetty的WekSocketServlet写了一个简单的WebIM程序,正好第一次瞥见WebSocket的狰容。

服务器端
jetty 7.1.5
客户端
Chromium 5.0.375.86

通过wireshark抓包获得这样一些数据:
var _ws = new WebSocket(“ws://127.0.0.1:8080/nothing”)
这个环节创建WebSocket,浏览器与服务器端进行handshake,发送请求

GET /nothing HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: 127.0.0.1:8080
Origin: http://127.0.0.1:8080

客户端发出一个Upgrade头,upgrade头在RFC2616 14.42定义

The Upgrade general-header allows the client to specify what additional communication protocols it supports and would like to use if the server finds it appropriate to switch protocols.

Upgrade必须被放入Connection头中标示这是一个Upgrade请求
Connection定义在RFC2616 14.10中:

The Connection general-header field allows the sender to specify options that are desired for that particular connection and MUST NOT be communicated by proxies over further connections.

Origin头还没有进入RFC,他的标准草案可以在这里找到,W3C的标准草案Cross-Origin Resource Sharing定义Origin Header:

The Origin header indicates where the cross-origin request or preflight request originates from.

Origin头的提出是为了解决CSRF的潜在危险,通过Origin服务器端可以获知请求的来源,进而判断其合法性。也就是说将跨域安全性检查的责任交给了服务器端,浏览器端采取信任的策略,避免了原先对跨域一棍子打死的做法。
Jetty 7的org.eclipse.jetty.servlets.CrossOriginFilter对这个头进行了处理。

此外,handshake请求的header中还允许一个Sec-WebSocket-Protocol,用于对服务器端指定一个子协议(应用协议)。

服务器端应答

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://127.0.0.1:8080
WebSocket-Location: ws://127.0.0.1:8080/nothing

Websocket连接建立。此后,服务器端和客户端可以实现bidirectional的通信,消息体即websocket.send(msg)中的纯文本。要实现这样的机制,浏览器和服务器间需要建立至少两个连接。目前,WebSocket协议中还没有规定客户端对服务器端的连接数限制。不过关于这个限制,RFC2616(HTTP1.1)中规定

Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy.

对此,另一个Bayeux协议倒是已经有了明确的限制:

the Bayeux protocol MUST NOT require any more than 2 HTTP requests to be simultaneously handled by a server in order to handle all application (Bayeux based or otherwise) requests from a client.

到此,客户端和服务器端已经可以建立双工的通信,这也是浏览器级别实现WebSocket协议的最大优点。而对于Firefox 3.x, IE x.x等等,只能在现有的HTTP连接机制上实现WebSocket,如通过long polling和callback polling的方式,但终归无法实现真正双工的通信。

The post is brought to you by lekhonee v0.7

fixing "libmozjs" missing when using mongodb on Ubuntu lucid

Problem
When running mongod/mongo/mongos, you got message like this:
mongod: error while loading shared libraries: libmozjs.so: cannot open shared object file: No such file or directory

Solution
Make sure you have xulrunner-dev installed:
sudo apt-get install xulrunner-dev

then find libmozjs on your filesystem:
sudo locate libmozjs

in lucid, it’s supposed to locate at:
/usr/lib/xulrunner-1.9.2.6/libmozjs.so

(and some other directories, such as firefox / thunderbird / seamonkey)

Just create a symbol link:
sudo ln -s /usr/lib/xulrunner-1.9.2.6/libmozjs.so /usr/lib/

try to restart mongodb:
sudo service mongodb start

take a look at process list:
ps aux | grep mongo

it works.

The post is brought to you by lekhonee v0.7

Python获取本机IP

除了用inetface库和分析ifconfig输出以外,一个比较简单的获取本机IP的方法:

import socket
def get_local_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("sdo.com",80))
    return s.getsockname()[0]

参考 http://stackoverflow.com/questions/166506/finding-local-ip-addresses-in-python

Maven recipe #1: Test Java code with groovy

问题: 受够了,不想写Java了,写个含有数据的map还要new出来一个一个put进去,想用groovy解决单元测试
解决: gmaven+groovy eclipse插件可以解决这个需求
在pom.xml中添加gmaven的依赖,注意,仅用来测试。老大不让生产代码里有不可靠的东西。

...
        <dependency>
            <groupId>org.codehaus.groovy.maven.runtime</groupId>
            <artifactId>gmaven-runtime-default</artifactId>
            <version>1.0-rc-3</version>
            <scope>test</scope>
        </dependency>
...
            <plugin>
                <groupId>org.codehaus.groovy.maven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <version>1.0-rc-3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generateStubs</goal>
                            <goal>compile</goal>
                            <goal>generateTestStubs</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

在eclipse中新建source folder, src/test/groovy,在其中创建groovy test case即可

开始实践Poromodo Technique

看了@juvenxv的博客介绍Poromodo Technique Illustrated一书,结合我现在低下的工作效率,我决定实践一下这个方法。

  • 一张TODO表记录今天的计划
  • 一张Activity Inventory表用于记录长期的任务,标记已完成的任务
  • 一张Record表统计每天完成的任务数量

一个Poromodo持续25分钟,在这25分钟内只专注当前任务。Poromodo间隙用来给大脑做缓冲,清空前一个任务的影响,以便下一个Poromodo开始时快速切换到相应任务。

应对Interruption,对internal的accept, record & continue,一个poromodo作为一个原子单元不可被打断,一旦被打断应该重新开始。
对external的,评估重要性,分别拒绝、延后、安排时间、安排回调。