• Feeds

  • Archive for March, 2009


    BlackBerry黑莓8700优缺点

    用了BlackBerry 8700一两周了,感觉如下。

    1. 自带的浏览器很不错, 感觉比Opera mini好用,支持qwerty全键盘快捷键
    2. 输入速度很快,键盘设计很合理 尤其是英文, 可以很方便记录很多临时想法, 比如这篇文章刚才在地铁上就完成了
    3. 可以和电脑同步address, calender, task.
    4. 支持多任务及copy/paste
    5. 常用BlackBerry软件8700都支持
    6. 可以给手机设置密码, 手机丢了也无需担心数据安全
    7. 可以给PC做modem通过移动gprs/edge上网
    8. 价格便宜, 大白菜价,可能是公司最便宜的手机了, 目前价格400-600元。

    缺点
    1. 上网经常碰到请求超时(4.2ROM),刷机4.5后解决,但是4.5没有自带拼音输入法,第三方的输入法兼容性稍差。
    2. 待机时间不够长,每天上网1-2小时待机2-3天
    3. 外形稍宽,一只手操作比如切换到滚轮和回车键有点费力,长相一般,不过自己觉得还行。
    4. 没有相机和扩展存储卡

    另外8700引以为豪的是越狱中的专用手机

    blackberry 8700

    如何写nginx module

    对于一些访问量特别大,业务逻辑也相对简单的Web调用来说,通过一个nginx module来实现是一种比较好的优化方法。实现一个nginx module实际上比较简单。

    1. nginx 配置添加

    ./configure --add-module=/path/to/module1/source

    2. 添加 /path/to/module1/source/config 文件,内容

    ngx_addon_name=ngx_http_hello_module
    HTTP_MODULES="$HTTP_MODULES ngx_http_hello_module"
    NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_module.c"
    CORE_LIBS="$CORE_LIBS -lfoo"

    最后一行如果没有使用其他library, 可以去掉

    3. 源代码 /path/to/module1/source/ngx_http_hello_module.c, 主要的业务逻辑在make_http_get_body 中完善。典型的hello world源代码如下

    #include <ngx_config.h>
    #include <ngx_core.h>
    #include <ngx_http.h>
    
    #define OUT_BUFSIZE 256
    
    static char *ngx_http_hello_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    static char *ngx_http_foo_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    
    static ngx_int_t ngx_http_hello_process_init(ngx_cycle_t *cycle);
    static void ngx_http_hello_process_exit(ngx_cycle_t *cycle);
    
    static ngx_int_t make_http_header(ngx_http_request_t *r);
    static ngx_int_t make_http_get_body(ngx_http_request_t *r, char *out_buf);
    
    static char g_foo_settings[64] = {0};
    
    /* Commands */
    static ngx_command_t  ngx_http_hello_commands[] = {
        { ngx_string("ngx_hello_module"),
          NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
          ngx_http_hello_set,
          NGX_HTTP_LOC_CONF_OFFSET,
          0,
          NULL },
    
        { ngx_string("hello"),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_http_foo_set,
          NGX_HTTP_LOC_CONF_OFFSET,
          0,
          NULL },  
    
          ngx_null_command
    };
    
    static ngx_http_module_t  ngx_http_hello_module_ctx = {
        NULL,                                  /* preconfiguration */
        NULL,                                     /* postconfiguration */
    
        NULL,                                  /* create main configuration */
        NULL,                                  /* init main configuration */
    
        NULL,                                  /* create server configuration */
        NULL,                                  /* merge server configuration */
    
        NULL,                                  /* create location configuration */
        NULL                                   /* merge location configuration */
    };
    
    /* hook */
    ngx_module_t  ngx_http_hello_module = {
        NGX_MODULE_V1,
        &ngx_http_hello_module_ctx,              /* module context */
        ngx_http_hello_commands,                 /* module directives */
        NGX_HTTP_MODULE,                       /* module type */
        NULL,                                  /* init master */
        NULL,                                  /* init module */
        ngx_http_hello_process_init,             /* init process */
        NULL,                                  /* init thread */
        NULL,                                  /* exit thread */
        ngx_http_hello_process_exit,             /* exit process */
        NULL,                                  /* exit master */
        NGX_MODULE_V1_PADDING
    };
    
    /* setting header for no-cache */
    static ngx_int_t make_http_header(ngx_http_request_t *r){
        ngx_uint_t        i;
        ngx_table_elt_t  *cc, **ccp;
    
        r->headers_out.content_type.len = sizeof("text/html") - 1;
        r->headers_out.content_type.data = (u_char *) "text/html";
        ccp = r->headers_out.cache_control.elts;
        if (ccp == NULL) {
    
            if (ngx_array_init(&r->headers_out.cache_control, r->pool,
                               1, sizeof(ngx_table_elt_t *))
                != NGX_OK)
            {
                return NGX_ERROR;
            }
    
            ccp = ngx_array_push(&r->headers_out.cache_control);
            if (ccp == NULL) {
                return NGX_ERROR;
            }
    
            cc = ngx_list_push(&r->headers_out.headers);
            if (cc == NULL) {
                return NGX_ERROR;
            }
    
            cc->hash = 1;
            cc->key.len = sizeof("Cache-Control") - 1;
            cc->key.data = (u_char *) "Cache-Control";
    
            *ccp = cc;
    
        } else {
            for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
                ccp[i]->hash = 0;
            }
    
            cc = ccp[0];
        }
    
        cc->value.len = sizeof("no-cache") - 1;
        cc->value.data = (u_char *) "no-cache";
    
        return NGX_OK;
    }
    
    static ngx_int_t make_http_get_body(ngx_http_request_t *r, char *out_buf){
        char *qs_start = (char *)r->args_start;
        char *qs_end = (char *)r->uri_end;
        char uri[128] = {0};
        char *id;
    
        if (qs_start == NULL || qs_end == NULL){
            return NGX_HTTP_BAD_REQUEST;
        }
        if ((memcmp(qs_start, "id=", 3) == 0)){
            id = qs_start + 3;
            *qs_end = '\0';
        }else{
            return NGX_HTTP_BAD_REQUEST;
        }
        snprintf(uri, r->uri.len + 1, "%s", r->uri.data);
        sprintf(out_buf, "Author: http://timyang.net/\nconfig=%s\nid=%snuri=%s\nret=%lx\n", g_foo_settings, id, uri, ngx_random());
        return NGX_OK;
    }
    
    static ngx_int_t
    ngx_http_hello_handler(ngx_http_request_t *r)
    {
        ngx_int_t     rc;
        ngx_buf_t    *b;
        ngx_chain_t   out;
    
        /* Http Output Buffer */
        char out_buf[OUT_BUFSIZE] = {0};
    
        if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
            return NGX_HTTP_NOT_ALLOWED;
        }
    
        rc = ngx_http_discard_request_body(r);
    
        if (rc != NGX_OK && rc != NGX_AGAIN) {
            return rc;
        }
    
        /* make http header */
        rc = make_http_header(r);
        if (rc != NGX_OK) {
            return rc;
        }
    
        if (r->method == NGX_HTTP_HEAD) {
            r->headers_out.status = NGX_HTTP_OK;
            return ngx_http_send_header(r);
        } else if (r->method == NGX_HTTP_GET) {
            /* make http get body buffer */
            rc = make_http_get_body(r, out_buf);
            if (rc != NGX_OK) {
                return rc;
            }
        } else {
            return NGX_HTTP_NOT_ALLOWED;
        }
    
        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
        if (b == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
    
        out.buf = b;
        out.next = NULL;
    
        b->pos = (u_char *)out_buf;
        b->last = (u_char *)out_buf + strlen(out_buf);
        b->memory = 1;
        b->last_buf = 1;
        r->headers_out.status = NGX_HTTP_OK;
        r->headers_out.content_length_n = strlen(out_buf);
    
        rc = ngx_http_send_header(r);
    
        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
            return rc;
        }
    
        return ngx_http_output_filter(r, &out);
    }
    
    static char *
    ngx_http_hello_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    
        /* register hanlder */
        clcf->handler = ngx_http_hello_handler;
    
        return NGX_CONF_OK;
    }
    
    static char *
    ngx_http_foo_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_str_t *value = cf->args->elts;
        memcpy(g_foo_settings, value[1].data, value[1].len);
        g_foo_settings[value[1].len] = '�';
    
        return NGX_CONF_OK;
    }
    
    static ngx_int_t
    ngx_http_hello_process_init(ngx_cycle_t *cycle)
    {
        // do some init here
        return NGX_OK;
    }
    
    static void
    ngx_http_hello_process_exit(ngx_cycle_t *cycle)
    {
        return;
    }

    4. 配置文件 nginx.conf

            location /hello {
                ngx_hello_module;
                hello 1234;
            }

    5. 访问 http://localhost/hello?id=1

    也可参考更详细的英文说明:
    Emiller’s Guide To Nginx Module Development

    Python thread socket server

    从网上参考了一些代码,实现了一个Python实现的基于线程的socket server, 用来实现各种服务系统的原型。放在这里供以后参考。

    #!/usr/bin/env python
    import threading
    import SocketServer
    
    users = []
    
    class MyTCPHandler(SocketServer.StreamRequestHandler):
        def handle(self):
            username = None
            while True:
                self.data = self.rfile.readline().strip()
                cur_thread = threading.currentThread()
                print "RECV from ", self.client_address[0]
                cmd = self.data
                if cmd == None or len(cmd) == 0:
                    break;
                print cmd
                # business logic here
                try:
                    if cmd.startswith('echo'):
                        result = cmd[5:]
                    elif cmd.startswith('login'):
                        username = cmd[6:]
                        users.append({username:self.wfile})
                        result = username + ' logined.'
                    elif cmd == 'quit':
                        break
                    else:
                        result = 'error cmd'
                    self.wfile.write(result)
                    self.wfile.write('\n')
                except:
                    print 'error'
                    break
            try:
                if username != None:
                    users.remove(username)
            except:
                pass
            print username, ' closed.'
    
    class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
        pass
    
    if __name__ == "__main__":
        HOST, PORT = "localhost", 9999
    
        server = ThreadedTCPServer((HOST, PORT), MyTCPHandler)
        server_thread = threading.Thread(target=server.serve_forever)
        server_thread.setDaemon(True)
        server_thread.start()
        server.serve_forever()