Archive for Erlang

Erlang http 客户端库 httpc 的例子

1 > inets:start().
ok
2> http:set_options([{cookies, enabled}]).
ok
3>{ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
httpc:request(get, {“http://www.google.com”, [{“connection”, “close”}]},
[], []).

httpc:reset_cookies().
httpc:store_cookies([{“set-cookie”,”TESTID=set”}], URL). %% 注意这里 URL 的格式是 http://www.a.com/aaa ,httpc 将使用 www.a.com /aaa 。
httpc:which_cookies().

erlang 的 cookie 在重定向时会多发一次cookie 下面是一个例子:
第一次请求的时候没有问题:

GET / HTTP/1.1
te:
host: www.google.com
connection: close

HTTP/1.1 302 Found
Location: http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1305091134484018&usg=AFQjCNGVKwFoguLJsXcF2r-iSVP8pGVjAg
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=9837e8b8b27a4644:FF=0:NW=1:TM=1305091104:LM=1305091104:S=6c4IRHZYSSNbdUuu; expires=Fri, 10-May-2013 05:18:24 GMT; path=/; domain=.google.com
Date: Wed, 11 May 2011 05:18:24 GMT
Server: gws
Content-Length: 376
X-XSS-Protection: 1; mode=block
Connection: close


GET /url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1305091134484018&usg=AFQjCNGVKwFoguLJsXcF2r-iSVP8pGVjAg HTTP/1.1
te:
host: www.google.com.hk
connection: close

HTTP/1.1 302 Found
Location: http://www.google.com.hk/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=9e289483a992f2d3:FF=2:LD=zh-CN:NW=1:TM=1305091104:LM=1305091104:S=yZ76ERBlUrruTyf8; expires=Fri, 10-May-2013 05:18:24 GMT; path=/; domain=.google.com.hk
Date: Wed, 11 May 2011 05:18:24 GMT
Server: gws
Content-Length: 222
X-XSS-Protection: 1; mode=block
Connection: close


GET / HTTP/1.1
te:
host: www.google.com.hk
connection: close
cookie: $Version=0; PREF=ID=9e289483a992f2d3:FF=2:LD=zh-CN:NW=1:TM=1305091104:LM=1305091104:S=yZ76ERBlUrruTyf8; $Path=/; $Domain=.google.com.hk

HTTP/1.1 200 OK
Date: Wed, 11 May 2011 05:18:24 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=GB2312
Set-Cookie: NID=46=cgV8OXUUqoZuZBzyUYB3hZC1sL51UZhsZ8pG6g_tydOhFzj1XIRCjSUTSPge97fbOmafxdA6GHZh1eKokS7Q5sj9JHgi7SmYtW3oPZIE_Sy6FYt8dQxUJ3hstV-RRNrv; expires=Thu, 10-Nov-2011 05:18:24 GMT; path=/; domain=.google.com.hk; HttpOnly
Server: gws
X-XSS-Protection: 1; mode=block
Connection: close

第二次就会出现问题了

GET / HTTP/1.1
te:
host: www.google.com
connection: close
cookie: $Version=0; PREF=ID=9837e8b8b27a4644:FF=0:NW=1:TM=1305091104:LM=1305091104:S=6c4IRHZYSSNbdUuu; $Path=/; $Domain=.google.com

HTTP/1.1 302 Found
Location: http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1305091219434173&usg=AFQjCNGrXvfQAy3xZMSZz2k2q4slxaeW4Q
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Date: Wed, 11 May 2011 05:19:49 GMT
Server: gws
Content-Length: 376
X-XSS-Protection: 1; mode=block
Connection: close


GET /url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1305091219434173&usg=AFQjCNGrXvfQAy3xZMSZz2k2q4slxaeW4Q HTTP/1.1
te:
host: www.google.com.hk
connection: close
cookie: $Version=0; PREF=ID=9837e8b8b27a4644:FF=0:NW=1:TM=1305091104:LM=1305091104:S=6c4IRHZYSSNbdUuu; $Path=/; $Domain=.google.com
cookie: $Version=0; PREF=ID=9e289483a992f2d3:FF=2:LD=zh-CN:NW=1:TM=1305091104:LM=1305091104:S=yZ76ERBlUrruTyf8; $Path=/; $Domain=.google.com.hk; NID=46=cgV8OXUUqoZuZBzyUYB3hZC1sL51UZhsZ8pG6g_tydOhFzj1XIRCjSUTSPge97fbOmafxdA6GHZh1eKokS7Q5sj9JHgi7SmYtW3oPZIE_Sy6FYt8dQxUJ3hstV-RRNrv; $Path=/; $Domain=.google.com.hk

HTTP/1.1 302 Found
Location: http://www.google.com.hk/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=9837e8b8b27a4644:U=ab1c598a16c1d65a:FF=2:LD=zh-CN:NW=1:TM=1305091104:LM=1305091189:S=oioGImT3t2mz6D-J; expires=Fri, 10-May-2013 05:19:49 GMT; path=/; domain=.google.com.hk
Date: Wed, 11 May 2011 05:19:49 GMT
Server: gws
Content-Length: 222
X-XSS-Protection: 1; mode=block
Connection: close


GET / HTTP/1.1
te:
host: www.google.com.hk
connection: close
cookie: $Version=0; PREF=ID=9837e8b8b27a4644:FF=0:NW=1:TM=1305091104:LM=1305091104:S=6c4IRHZYSSNbdUuu; $Path=/; $Domain=.google.com
cookie: $Version=0; PREF=ID=9e289483a992f2d3:FF=2:LD=zh-CN:NW=1:TM=1305091104:LM=1305091104:S=yZ76ERBlUrruTyf8; $Path=/; $Domain=.google.com.hk; NID=46=cgV8OXUUqoZuZBzyUYB3hZC1sL51UZhsZ8pG6g_tydOhFzj1XIRCjSUTSPge97fbOmafxdA6GHZh1eKokS7Q5sj9JHgi7SmYtW3oPZIE_Sy6FYt8dQxUJ3hstV-RRNrv; $Path=/; $Domain=.google.com.hk
cookie: $Version=0; NID=46=cgV8OXUUqoZuZBzyUYB3hZC1sL51UZhsZ8pG6g_tydOhFzj1XIRCjSUTSPge97fbOmafxdA6GHZh1eKokS7Q5sj9JHgi7SmYtW3oPZIE_Sy6FYt8dQxUJ3hstV-RRNrv; $Path=/; $Domain=.google.com.hk; PREF=ID=9837e8b8b27a4644:U=ab1c598a16c1d65a:FF=2:LD=zh-CN:NW=1:TM=1305091104:LM=1305091189:S=oioGImT3t2mz6D-J; $Path=/; $Domain=.google.com.hk

HTTP/1.1 200 OK
Date: Wed, 11 May 2011 05:19:49 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=Big5
Set-Cookie: PREF=ID=9837e8b8b27a4644:U=ab1c598a16c1d65a:FF=0:NW=1:TM=1305091104:LM=1305091189:S=8wPoAJMKqBOdg6M_; expires=Fri, 10-May-2013 05:19:49 GMT; path=/; domain=.google.com.hk
Server: gws
X-XSS-Protection: 1; mode=block
Connection: close

No comment »

Erlang Supervisor 的 error:{badmatch,{error,{{start_spec,{invalid_modules, ??? }} 错误解决

新人,刚开始学习 erlang ,使用 rebar 生成了一个标准的 otp 应用程序,往 Supervisor 加了一个 gen_server ,却通不过默认单元测试了。提示

 
gamexg@vps1:~/erl/cw$ rebar compile eunit
==> cw (compile)
Compiled src/cw_dnode.erl
Compiled src/cw_sup.erl
Compiled src/cw_app.erl
==> cw (eunit)

=INFO REPORT==== 18-Apr-2011::14:53:47 ===
    application: cw
    exited: {{start_spec,{invalid_modules,cw_dnode}},
             {cw_app,start,[normal,[]]}}
    type: temporary
cw_app: simple_test (module 'cw_app')...*failed*
::error:{badmatch,{error,{{start_spec,{invalid_modules,cw_dnode}},
                        {cw_app,start,[normal,[]]}}}}
  in function cw_app:simple_test/0


=======================================================
  Failed: 1.  Skipped: 0.  Passed: 0.
Cover analysis: /home/gamexg/erl/cw/.eunit/index.html
ERROR: One or more eunit tests failed.

最后发现原因是回调模块应该是列表,我却直接把模块名填上了….

 
-module(cw_sup).

-behaviour(supervisor).

%% API
-export([start_link/0]).

%% Supervisor callbacks
-export([init/1]).

%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).

%% ===================================================================
%% API functions
%% ===================================================================

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

%% ===================================================================
%% Supervisor callbacks
%% ===================================================================

init([]) ->
    {ok, { {one_for_one, 5, 100}, 
        [
            {dnode,
                {cw_dnode,start_link,[]},
                permanent,
                10000,
                worker,
                cw_dnode                                 % 这里错了,应该是 [cw_dnode] ,是列表。
            }
        ]
       } }.

No comment »

Erlang 编译并运行程序

在 erl shell 中编译运行

ERLANG程序设计-code\code>erl
Eshell V5.8.2 (abort with ^G)
1> c(hello).
{ok,hello}
2> hello:start().
Hello world
ok
3>

在命令提示符下编译运行

ERLANG程序设计-code\code>erlc hello.erl
ERLANG程序设计-code\code>erl -noshell -s hello start -s init stop
Hello world

ERLANG程序设计-code\code>

快速脚本

-eval 参数可以在 os 命令行中执行任意的erlang函数,例如:

$ erl -eval ‘io:format(“Hello world~n”).’ -noshell -s init stop
Hello world
$ erl -eval ‘io:format(“Memory:~p~n”,[erlang:memory(total)]).’ -noshell -s init stop
Memory:2854918
$
上面这个命令在windows下无输出,原因是单引号的问题,将单引号换成双引号就可以了,可能是windows直接将单引号传递给了erl,被erl当作了原子了。
windows下需要执行下面的命令
D:\My Dropbox\Erlang\ERLANG程序设计-code\code>erl -eval “io:format(\”Hello world
\”).” -noshell -s init stop
Hello world
D:\My Dropbox\Erlang\ERLANG程序设计-code\code>
erlc hello.erl 编译文件hello.erl,生成名为hello.beam的目标代码文件。
-noshell 表示启动erlang,但是关闭shell,因此不会看到erlang提示信息。
-s hello start 表示运行函数 hello:start(). ,-s 执行模板函数时模板必须已经编译过,否则出现下面的错误:
ERLANG程序设计-code\code>erl  -noshell -s hello start -s init stop
{“init terminating in do_boot”,{undef,[{hello,start,[]},{init,start_it,1},{init,start_em,1}]}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
-s init stop 表示运行 init:stop() 函数。当有多个 -s 参数时,会按顺序对每个-s命令有一个apply语句进行解释运行,一旦一个运行完毕,则继续执行下一个命令。

No comment »

导入测试数据到 Mnesia 数据库

假如我们开始玩一个关于健康食品的小型数据库,可输入下列数据到文件data.txt:

{tables,[
    {fruit, [{attributes, [name, color, taste]}]},
    {vegetable, [{attributes, [name, color, taste, price]}]}
]}.

{fruit, orange, orange, sweet}.
{fruit, apple, green, sweet}.
{vegetable, carrot, orange, carrotish, 2.55}.
{vegetable, potato, yellow, none, 0.45}.

下列Erlang shell会话显示如何加载fruits数据库:

 $ erl
Erlang (BEAM) emulator version 5.6.3 [source] [smp:2] [async-threads:0] [kernel-poll:false]

Eshell V5.6.3 (abort with ^G)
1> mnesia:start(). % 虽然 mnesia:load_textfile 也会启动数据库,但是在处理上次遗留的内存数据库上有问题,
会保留上次非正常退出时的内存表的结构,造成本次 mnesia:load_textfile 操作失败。出现注1的错误,造成无法导入本
次的数据。
ok
2> mnesia:load_textfile("data.txt").
New table fruit
New table vegetable
{atomic,ok}
3> mnesia:info().
---> Processes holding locks <--- ---> Processes waiting for locks <--- ---> Participant transactions <--- ---> Coordinator transactions <--- ---> Uncertain transactions <--- ---> Active tables <--- vegetable : with 2 records occupying 320 words of mem fruit : with 2 records occupying 312 words of mem schema : with 3 records occupying 622 words of mem ===> System info in version "4.4.3", debug level = none <=== opt_disc. Directory "/home/gamexg/erl/mnesia/Mnesia.nonode@nohost" is NOT used. use fallback at restart = false running db nodes = [nonode@nohost] stopped db nodes = [] master node tables = [] remote = [] ram_copies = [fruit,schema,vegetable] disc_copies = [] disc_only_copies = [] [{nonode@nohost,ram_copies}] = [schema,fruit,vegetable] 5 transactions committed, 0 aborted, 0 restarted, 0 logged to disc 0 held locks, 0 in queue; 0 local transactions, 0 remote 0 transactions waits for other nodes: [] ok 4>

这里我们能够看到怎样从一个规范的文本文件来初始化数据库管理系统。

注1:不使用mnesia:start 启动数据库直接载入数据会使上次运行的内存表未被清除,而和本次导入的表冲突,导入失败。

$ erl
Erlang (BEAM) emulator version 5.6.3 [source] [smp:2] [async-threads:0] [kernel-poll:false]

Eshell V5.6.3 (abort with ^G)
1> mnesia:load_textfile(“data.txt”).
** Table fruit already exists on nowhere, just entering data
** Table vegetable already exists on nowhere, just entering data
{aborted,{no_exists,fruit}}
2>

No comment »