Friday, November 02, 2007

XMLSocket(Flex) กับ Erlang

protocol ของ XMLSocket กำหนดไว้ว่า ข้อมูลที่ส่งแต่ละชุดจะปิดท้ายด้วย Zero Byte
นี่คือ code ง่ายๆของ Erlang ที่เปิดรับข้อมูลที่ส่งจาก XMLSocket
%% echo server แบบง่ายๆ
start() ->
{ok, Listen} = gen_tcp:listen(4114, [list,
{reuseaddr, true},
{active, true}]),
{ok, Socket} = gen_tcp:accept(Listen),
gen_tcp:close(Listen),
loop(Socket).

loop(Socket) ->
receive
{tcp, Socket, Data} ->
%% ก่อน parse ก็ให้ตัด byte สุดท้ายที่เป็น zero byte ออกก่อน
Txt = xmlutil:parse(strip(Data, right, $\0)),
%% ตอนส่งกลับก็ให้ต่อท้ายด้วย zero byte กลับไปด้วย
gen_tcp:send(Socket, concat(xmlutil:encode(concat(Txt, " pok")), [0])),
loop(Socket);
{tcp_closed, Socket} ->
io:format("Socket closed~n")
end.


ตัว XMLSocket ถึงจะตั้งชื่อให้มี XML นำหน้า แต่จริงๆแล้วมันก็เหมือน XMLHttpRequest ของ javascript
ที่ใช้ส่งข้อมูลอะไรก็ได้ ตามแต่ใจเรา
อย่างที่ผมเอามาใช้ แทนที่จะส่งข้อมูลมาให้ erlang ในรูปแบบ XML (ซึ่งเราขี้เกียจ parse)
ก็ให้ส่งมาเป็น erlang tuple เลย จะได้เอาไป execute ต่อได้ง่ายๆ

ใน erlang, มันมีวิธี eval String ง่ายๆดังนี้
eval(S,Environ) ->
{ok,Scanned,_} = erl_scan:string(S),
{ok,Parsed} = erl_parse:parse_exprs(Scanned),
erl_eval:exprs(Parsed,Environ).

ลอง run ดู
2> simple_server:eval("X=1+2.",[]).
{value,3,[{'X',3}]}
3> simple_server:eval("{plus,1,2}.",[]).
{value,{plus,1,2},[]}


เวลาเราเอาไปใช้กับ XMLSocket ก็จะเขียนประมาณนี้
loop(Socket) ->
receive
{tcp, Socket, Data} ->
Str = strip(Data,right,$\0),
{value, Cmd, _} = eval(Str,[]),
Result = execute(Cmd),
gen_tcp:send(Socket, concat(Result, [0])),
loop(Socket);
{tcp_closed, Socket} ->
io:format("Socket closed~n")
end.

execute({hello}) -> "world";
execute({who}) -> "pok";
execute({plus, X, Y}) -> integer_to_list(X+Y).


Update:
กรณีถ้าต้องการ parse จาก String เป็น Term
ใช้ code แค่นี้ก็พอ
eval(S) ->
{ok,Scanned,_} = erl_scan:string(S),
{ok,Term} = erl_parse:parse_term(Scanned),
Term.

Related link from Roti

Thursday, November 01, 2007

เตรียมการ codefest

เหลืออีก 4 วันก็ถึง codefest แล้ว
ช่วงนี้ก็เลยวุ่นอยู่กับการเตรียมการ
เนื่องจากหัวข้อที่ผมเลือกทำ codefest,
ผมเลือกจากสิ่งที่ไม่รู้หรือไม่เคยทำ
ตอนนี้ก็เลยสนุกกับการบุกเบิกในสิ่งที่ไม่รู้

โปรเจคแรก เป็นโปรเจคที่ present ข้อมูลผ่าน Map
ซึ่งต้องยุ่งกับ MapServer



ความยากจะอยู่ที่ jargon หรือ Term ต่างๆที่เป็นเรื่องทางภูมิศาสตร์
เช่นถ้าใช้ wms (web service ของพวก GIS)
ค่า SRS (Spatial Referential System) ของไทยต้องกำหนดเป็นค่าอะไร?
ความยุ่งที่สอง ก็คือ ตอน present map ด้วย javascript
ผมเลือกใช้ Ka-Map ซึ่งมี feature ทำนอง Google Map
แต่ Ka-Map มันใช้ server-side เป็น php
ซึ่งผมต้องการเปลี่ยนเป็น Rails แทน
โชคดีที่มี project Ruby In Space เขาใช้ rails เป็น server-side เช่นกัน
ก็เลยไปเอา code ของ project นั้นมาใช้
แต่ก็ไม่วายโชคร้าย ตรง code base มันเก่าแล้ว
มันก็เลยมี error จากการที่ api ของ mapserver มันเปลี่ยน signature
แต่ก็แก้ได้ไม่ยาก
ไปยากตรงงมว่ามันใช้อย่างไร
ส่วนของ embeded code, ผมทำแต่ส่วน high level ก็เลยไม่มีปัญหามากนัก
เจอ bug ตรง firmware หน่อยหนึ่ง

โปรเจคที่สองเป็นโปรเจคที่ทำด้วย erlang + flex
ความยากอยู่ที่ นานๆจะใช้มันที
มันก็เลยฝึดๆ
กว่าจะทำอะไรได้ที ต้องเปิดคู่มือวุ่นวาย

แต่ที่ต้องยกให้เป็นพระเอกของงานนี้ก็คือ
vmware server
เพราะแค่เตรียมสภาพแวดล้อมเป็น vertual machine
แล้วแจกจ่ายให้ทืม ก็ช่วยลดแรงเสียดทานไปได้เยอะแล้ว
(แรงเสียดทานของ version conflict, library ไม่ครบ, config ไม่ถูก, Windows vs Linux)

Related link from Roti