目前正在進行gtalk 的機器人實作,我想把google的(英翻中)翻譯做在gtalk 上,這當然不是什麼新鮮的事,而且目前google 已經釋出相關的功能,不過;獨缺英文->繁體中文,沒錯! 我就是想做世界第一個英翻中(繁體)的機器人,事實上我只是想展示公司在xmpp 上的應用能夠做到什麼程度,如果我們撇開rfid middle 的xmpp server應用,這應該是我第一次在gtalk 上做相關應用
目前;已經突破gtalk 使用TLS 的認證部份,整個工作大概完成了40%,希望能夠在這個星期前釋出第一個版本
我的雲端生活網 - Life+
Monday, December 31, 2007
Thursday, December 27, 2007
Sunday, December 16, 2007
Concurrent Programming II
1.Concurrency is easy…?
( http://armstrongonsoftware.blogspot.com/2006/08/concurrency-is-easy.html )
2.Sequential Programming
-module(factorial).
-export([factoriala/1, factorialb/1, factorialc/1, factoriald/1]).
%Simplest:
factoriala(0) -> 1;
factoriala(N) -> N * factoriala(N - 1).
%Using function guards:
factorialb(0) -> 1;
factorialb(N) when N > 0 -> N * factorialb(N - 1).
%Using if:
factorialc(N) ->
if
N == 0 -> 1;
N > 0 -> N * factorialc(N - 1)
end.
%Using case:
factoriald(N) ->
case N of
0 -> 1;
N when N > 0 -> N * factoriald(N - 1)
end.
-module(set).
-export([new/0, add_element/2, del_element/2,is_element/2, is_empty/1, union/2, intersection/2]).
new() -> [].
is_element(H, [H|_]) -> true;
is_element(H, [_|Set]) -> is_element(H, Set);
is_element(_, []) -> false.
is_empty([]) -> true;
is_empty(_) -> false
add_element(X, Set) ->
case is_element(X, Set) of
true -> Set;
false -> [X|Set]
end.
del_element(X, [X|T]) -> T;
del_element(X, [Y|T]) -> [Y|del_element(X,T)];
del_element(_, []) -> [].
union([H|T], Set) -> union(T, add_element(H, Set));
union([], Set) -> Set.
intersection(S1, S2) -> intersection(S1, S2, []).
intersection([], _, S) -> S;
intersection([H|T], S1, S) ->
case is_element(H,S1) of
true -> intersection(T, S1, [H|S]);
false -> intersection(T, S1, S)
end.
3.concurrent programming
Processes and communication between processes are fundamental concepts in Erlang.
1. Process Create
Pid = spawn(Module, FunctionName, ArgumentList)
2. Inter-process Communication
Pid ! Message
receive
Message1 [when Guard1] ->Actions1 ;
Message2 [when Guard2] ->Actions2 ;
_AnyMessage -> Actions3 ;
after Timeout ->Action4
...
end.
3.Receiving messages from a specific process
Pid ! {self(),abc}
receive
{Pid,Msg} ->
...
end
4. Examples
a)
-module(cfac).
-export([start/0,loop/0]).
-import(factorial,[factoriala/1]).
start() ->spawn(counter, loop, []).
loop() ->
receive
{fac,Val}-> io:format("(from:~p)fac ~p=~p ~n",[node(),Val,
factoriala(Val)]),loop();
{exit}->io:format("end~n",[]);
_->loop()
end.
b) performance testing
c) programming with socket
-module(geturl).
-export([start/2,senddata/1,dataarrive/1,startN/3]).
-define(TCP_OPTIONS,[list, {packet, 0}, {active, false}, {reuseaddr,
true}]).
start(Url,Port)->
case gen_tcp:connect(Url,Port ,?TCP_OPTIONS ) of
{ok,CSocket}->geturl:senddata(CSocket);
{error,Why}->Why
end.
senddata(Socket)->
Data="GET / HTTP/1.0\r\nConnection: close\r\nCache-Control:
no-cache\r\n\r\n",
io:format("~p~n",[Socket]),
case gen_tcp:send(Socket,Data) of
ok->io:format("send:~p~n",[Data]),dataarrive(Socket);
{error, Why}->io:format("send_socket close:~p~n",[Why])
end.
dataarrive(Socket)->
case gen_tcp:recv(Socket, 0) of
{ ok, Data} ->io:format("receive:~p~n",[Data]),
dataarrive(Socket);
{error, Why} ->io:format("dataarrive_socket
close:~p~n",[Why])
end.
startN(_,_,0)->io:format("~p~n",["end"]);
startN(Url,Port,Num)->spawn(geturl,start,[Url,Port]),
startN(Url,Port,Num-1).
d) Distributes Programming
erl –sname local
erl –sname remote
Pid=rpc:call(remote@se6,cfac,start,[]).
Pid ! {fac,10}.
5.References
[1] J. Armstrong, R. Virding, C. Wikstr¨om, and M. Williams. Concurrent Programming in Erlang.
[2] J. Armstrong.Erlang Programming.
( http://armstrongonsoftware.blogspot.com/2006/08/concurrency-is-easy.html )
2.Sequential Programming
-module(factorial).
-export([factoriala/1, factorialb/1, factorialc/1, factoriald/1]).
%Simplest:
factoriala(0) -> 1;
factoriala(N) -> N * factoriala(N - 1).
%Using function guards:
factorialb(0) -> 1;
factorialb(N) when N > 0 -> N * factorialb(N - 1).
%Using if:
factorialc(N) ->
if
N == 0 -> 1;
N > 0 -> N * factorialc(N - 1)
end.
%Using case:
factoriald(N) ->
case N of
0 -> 1;
N when N > 0 -> N * factoriald(N - 1)
end.
-module(set).
-export([new/0, add_element/2, del_element/2,is_element/2, is_empty/1, union/2, intersection/2]).
new() -> [].
is_element(H, [H|_]) -> true;
is_element(H, [_|Set]) -> is_element(H, Set);
is_element(_, []) -> false.
is_empty([]) -> true;
is_empty(_) -> false
add_element(X, Set) ->
case is_element(X, Set) of
true -> Set;
false -> [X|Set]
end.
del_element(X, [X|T]) -> T;
del_element(X, [Y|T]) -> [Y|del_element(X,T)];
del_element(_, []) -> [].
union([H|T], Set) -> union(T, add_element(H, Set));
union([], Set) -> Set.
intersection(S1, S2) -> intersection(S1, S2, []).
intersection([], _, S) -> S;
intersection([H|T], S1, S) ->
case is_element(H,S1) of
true -> intersection(T, S1, [H|S]);
false -> intersection(T, S1, S)
end.
3.concurrent programming
Processes and communication between processes are fundamental concepts in Erlang.
1. Process Create
Pid = spawn(Module, FunctionName, ArgumentList)
2. Inter-process Communication
Pid ! Message
receive
Message1 [when Guard1] ->Actions1 ;
Message2 [when Guard2] ->Actions2 ;
_AnyMessage -> Actions3 ;
after Timeout ->Action4
...
end.
3.Receiving messages from a specific process
Pid ! {self(),abc}
receive
{Pid,Msg} ->
...
end
4. Examples
a)
-module(cfac).
-export([start/0,loop/0]).
-import(factorial,[factoriala/1]).
start() ->spawn(counter, loop, []).
loop() ->
receive
{fac,Val}-> io:format("(from:~p)fac ~p=~p ~n",[node(),Val,
factoriala(Val)]),loop();
{exit}->io:format("end~n",[]);
_->loop()
end.
b) performance testing
c) programming with socket
-module(geturl).
-export([start/2,senddata/1,dataarrive/1,startN/3]).
-define(TCP_OPTIONS,[list, {packet, 0}, {active, false}, {reuseaddr,
true}]).
start(Url,Port)->
case gen_tcp:connect(Url,Port ,?TCP_OPTIONS ) of
{ok,CSocket}->geturl:senddata(CSocket);
{error,Why}->Why
end.
senddata(Socket)->
Data="GET / HTTP/1.0\r\nConnection: close\r\nCache-Control:
no-cache\r\n\r\n",
io:format("~p~n",[Socket]),
case gen_tcp:send(Socket,Data) of
ok->io:format("send:~p~n",[Data]),dataarrive(Socket);
{error, Why}->io:format("send_socket close:~p~n",[Why])
end.
dataarrive(Socket)->
case gen_tcp:recv(Socket, 0) of
{ ok, Data} ->io:format("receive:~p~n",[Data]),
dataarrive(Socket);
{error, Why} ->io:format("dataarrive_socket
close:~p~n",[Why])
end.
startN(_,_,0)->io:format("~p~n",["end"]);
startN(Url,Port,Num)->spawn(geturl,start,[Url,Port]),
startN(Url,Port,Num-1).
d) Distributes Programming
erl –sname local
erl –sname remote
Pid=rpc:call(remote@se6,cfac,start,[]).
Pid ! {fac,10}.
5.References
[1] J. Armstrong, R. Virding, C. Wikstr¨om, and M. Williams. Concurrent Programming in Erlang.
[2] J. Armstrong.Erlang Programming.
[微程式-技術研討會] 12月份研討會 主講人 ZNUL [XMPP RFC3920 10-~15章]
Xmpp Rfc3920 10-~15章 研討會報告
10. 伺服器處理XML節的規則 (Server Rules for Handling XML Stanzas)
相容的伺服器實做必須(MUST)確保兩個實體之間的XML節按次序處理. 除了按次序處理的需求之外, 每個伺服器實作將包含它自己的遞送樹"delivery tree"以處理它接收到的節.這個樹決定一個節是否需要路由到其他域, 在內部處理, 還是遞送到和一個已連接的節點相關的資源. 以下規則適用:
________________________________________
10.1. 沒有'to'地址 (No 'to' Address)
如果這個節沒有'to'屬性, 伺服器應該(SHOULD)為發送它的實體處理這個節. 因為所有從其他伺服器收到的節必須(MUST)擁有'to'屬性, 這個規則僅適用於從一個連接到這台伺服器的已註冊實體(如一個用戶端)收到的節,如果這個伺服器收到一個沒有'to'屬性的出席資訊節, 伺服器應該(SHOULD)向那些訂閱了這個發送實體的出席資訊的所有實體廣播它, 如果可能的話(即時消息和出席資訊應用程式中出席資訊廣播的語義定義在XMPP-IM). 如果伺服器接收到一個IQ類型為 "get" 或 "set" 且沒有'to'屬性的節並且它理解這個節的名字空間下的內容, 它必須(MUST)為這個發送實體處理節(在這裏"處理"的含義是由相關的名字空間的語義所決定的)或返回一個錯誤給發送實體.
#c to s 可以不用有 to 屬性 ,因為c to s 預設的 to 即是 server
#若是出席訊息<presence>沒有to屬性,即為廣播給所有訂閱者,rfc3921第五章說明如下:
(5.1.1初始化出席資訊 :
建立起一個會話之後, 一個用戶端應該(SHOULD)發送初始化出席資訊給伺服器來通知它的通信可用性.如這裏定義的, 初始化出席資訊節 (1) 必須(MUST) 不擁有'to'屬性(這表示它是由伺服器代替用戶端發送的廣播) 並且 (2) 必須(MUST) 不擁有'type'屬性).
________________________________________
10.2. 外部域 (Foreign Domain) (s to s)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身或其子域配置的主機名不匹配, 伺服器應該(SHOULD)路由這個節到外部域(取決於本地服務規定或安全策略關於域間通信的規定).有兩種可能的情況:
- 一個伺服器to伺服器之間的流已經存在於兩個域之間: 發送者的伺服器透過這個已存在的流為這個外部域路由(轉送)這個節到授權伺服器 - 兩個域之間沒有伺服器to伺服器之間的流: 發送者伺服器 (1) 解析這個外部域的主機名(定義在伺服器間的通信Server-to-Server Communications (第十四章第四節)), (2) 在兩個域之間進行伺服器到伺服器的流協商(定義在 Use of TLS (第五章) 和 Use of SASL (第六章)), 然後 (3) 通過這個新建的流為外部域路由(轉送)這個節到授權伺服器
如果路由(轉送)到接收者的伺服器不成功, 發送者的伺服器必須(MUST)返回一個錯誤給發送者; 如果接收者的伺服器聯繫上了但是從接收者的伺服器遞送到接收者不成功, 接收者伺服器必須(MUST)透過發送者的伺服器返回一個錯誤給發送者.
________________________________________
10.3. 子域 (Subdomain) (?)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名的一個子功能變數名稱匹配,伺服器必須(MUST)自己處理這個節或路由這個節到專門負責這個子域的特定服務(如果子域被配置了),或者返回一個錯誤給發送者(如果子域沒有配置).
________________________________________
10.4. 純粹的域或特定的資源 (Mere Domain or Specific Resource)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名本身匹配,並且'to'屬性中的JID類型是<domain> 或 <domain/resource>, 伺服器(或其中定義的資源)必須(MUST)根據節的類型適當的處理這個節或返回一個錯誤節給發送者.
________________________________________
10.5. 同一域中的節點 (Node in Same Domain)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名本身匹配,並且'to'屬性中的JID類型是<node@domain> 或 <node@domain/resource>, 伺服器應該(SHOULD)遞送這個節到'to'屬性中的JID所指明的預定的接收者. 以下規則適用:
1. 如果這個JID包含一個資源ID(例如, 格式是<node@domain/resource>)並且存在一個連接的資源符合這個全JID, 接收者伺服器應該(SHOULD)遞送這個節給正確符合這個資源ID的流或會話.
2. 如果這個JID包含一個資源ID(例如, 格式是<node@domain/resource>)並且不存在一個連接的資源符合這個全JID, 接收者伺服器應該(SHOULD)返回一個<service-unavailable/> 節錯誤給發送者.
3. 如果這個JID的格式是<node@domain>並且存在至少一個此節點的連接資源, 接收伺服器應該( SHOULD)遞送這個節給至少其中一個已連接的資源, 依據應用程式定義的規則(一系列即時消息和出席資訊應用程式的遞送規則定義在XMPP-IM).
@Rfc3921第11章 伺服器處理XML節的規則有詳細的說明如下:
如果JID的格式是<user@domain>並且這個用戶至少有一個可用的資源, 接收者的伺服器必須(MUST)遵守以下規則:
1. 對於消息(message)節, 伺服器應該(SHOULD)遞送這個節給高優先順序的可用資源(如果這個資源沒有提供<priority/>元素的值, 伺服器應該(SHOULD)認為它提供的值為零). 如果兩個或更多的可用資源有相同的優先順序, 伺服器可以(MAY)使用一些其他的規則(例如, 最近的連接時間, 最近的活動時間, 或由一些<show/>值的層次所定義的最高的可用性) 來從它們中間選擇,或可以(MAY)遞送這個消息到所有這些資源. 無論如何, 伺服器不能(MUST NOT)遞送這個節到一個優先順序為負數的可用資源; 如果唯一的一個可用資源的優先順序是負數, 伺服器應該(SHOULD)當成沒有可用資源一樣處理這個消息(定義在後面). 另外, 伺服器不能(MUST NOT)重寫'to'屬性(換言之, 它必須(MUST)讓它保持<user@domain>而不是改成<user@domain/resource>).
2. 對於類型不是"probe"(探測)的出席資訊節, 伺服器必須(MUST)遞送這個節給所有可用的資源;對於出席資訊調查, 伺服器應該(SHOULD)基於定義在 出席資訊調查Presence Probes (第五章第一節第三小節)的規則來應答. 另外, 伺服器不能(MUST NOT)重寫'to'屬性(換言之, 它必須(MUST)保持<user@domain>而不是改為<user@domain/resource>).
3. 對於IQ節, 伺服器本身必須(MUST)代替用戶應答一個IQ result或一個IQ error, 並且不能(MUST NOT)遞送這個IQ節給任何可用的資源. 具體來說, 如果合格的名字空間的語義定義了一個伺服器可以提供的應答, 伺服器必須(MUST)代替用戶應答這個節; 如果沒有, 伺服器必須(MUST)應答一個<service-unavailable/>節錯誤.
<presence from='juliet@example.com/balcony'>
<priority>13</priority> => whose value is an integer between -128 and +127. rfc3921 2.2.2.3
</presence>
<presence from='juliet@example.com/balcony'>
<show>away</show> => chat dnd xa rfc3921 2.2.2.1
</presence>
________________________________________
11. XMPP中的XML用法 (XML Usage within XMPP)
________________________________________
11.1. 限制 (Restrictions)
XMPP是一個簡單的流式XML元素的專用協定用於接近即時地交換結構化資訊. 因為XMPP不需要任意的解析和所有的XML文檔, 所以XMPP不需要支援[XML]的所有功能. 特殊的, 適用以下限制.
關於XML生成, 一個XMPP實作不能(MUST NOT)在XML流中注入以下任何東西:
o 注釋 (第二章第五節[XML]) ,如 <!--XXX-->
o 處理指令(第二章第六節 同上) , target content parent
o 內部或外部的 DTD 子集 (第二章第八節 同上)
o 內部或外部的實體參考 (第四章第二節 同上) 除了預定實體以外(第四章第六節 同上)
o 字元資料或屬性值包含和預定實體列表中吻合的未逸出的unescaped字元(第四章第六節 同上); 這些字元必須(MUST)逸出 ,如 & < > …
關於XML處理, 如果一個XMPP實現接收到這些受限的XML資料,它必須(MUST)忽略這些資料.
________________________________________
11.2. XML 命名空間的名字和前綴詞 (XML Namespace Names and Prefixes)
XML名字空間[XML-NAMES]為所有XMPP相容的XML建立資料所有權的嚴格界限. 這個名字空間的基本功能是把結構上混合在一起的XML元素區分出不同的辭彙. 確保XMPP相容的XML有名字空間的感知能力使得任何允許的XML可以被結構化的混合到任何XMPP資料元素中. XML名字空間的名字和首碼的規則在下一小節中.
________________________________________
11.2.1. 流命名空間 (Streams Namespace)
在所有的XML流頭中必須聲明一個流名字空間. 流名字空間必須(MUST)是 'http://etherx.jabber.org/streams'. 元素名<stream/>和它的<features/>和<error/>子元素必須(MUST)在所有實例中符合這個流名字空間首碼. 一個實作應該(SHOULD)只為這些元素生成'stream:'首碼, 並且由於歷史原因可以(MAY)只接受'stream:'首碼.
________________________________________
11.2.2. 預設命名空間 (Default Namespace)
在所有的XML流中必須聲明一個預設的流名字空間用於定義允許的流根元素的一級子元素. 這個名字空間聲明對於初始化流和應答流必須(MUST)是相同的使得雙方的流都是合格一致的. 預設的名字空間聲明適用於流和所有在流中發送的節(除非由流名字空間或回撥名字空間的首碼顯式的符合另一個名字空間).
一個伺服器實現必須(MUST)支持以下兩個預設名字空間(由於歷史原因, 一些實現可能(MAY)只支持這兩個預設名字空間):
o jabber:client -- 當流用於用戶端和伺服器的通信時聲明這個預設名字空間
o jabber:server -- 當流用於兩個伺服器間的通信時聲明這個預設名字空間
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
一個用戶端實作必須(MUST)支持'jabber:client'預設名字空間,並且由於歷史原因可以(MAY)只支持這個預設名字空間.
如果預設名字空間是'jabber:client'或'jabber:server',一個實作不能(MUST NOT)在這個名字空間下為元素生成名字空間前綴詞. 一個實作不應該(SHOULD NOT)按照元素的內容(可能和流相反)生成不同於'jabber:client'和'jabber:server'名字空間前綴詞.
注意: 'jabber:client' 和 'jabber:server' 名字空間接近於相同但是用於不同的上下文(用戶端伺服器通信用'jabber:client' 而伺服器間通信用'jabber:server'). 這兩者之間僅有的不同在於在'jabber:client'中被發送的節中'to'和'from'屬性是可選的(OPTIONAL),而在'jabber:server'中被發送的節中它們是必需的(REQUIRED). 如果相容的實施接受一個符合'jabber:client'或'jabber:server'名字空間的流, 它必須(MUST)支援通用屬性(第九章第一節)和三個核心節類型(message, presence, 和IQ)的基本語義(第九章第二節).
________________________________________
11.2.3. 回撥名字空間 (Dialback Namespace)(?)
所有用於伺服器回撥的(第八章)元素都必須聲明一個回撥名字空間. 回撥名字空間的名字必須(MUST)是'jabber:server:dialback'. 所有符合此名字空間的元素必須(MUST)有首碼. 一個實現應該(SHOULD)只為這些元素生成'db:'首碼並且只可以(MAY)接受'db:'首碼.
________________________________________
11.3. 確認 (Validation)
除了注意'jabber:server'名字空間中關於節中'to'和'from'位址的規定,一個伺服器不需要為轉發到用戶端或其他伺服器負責檢查XML元素;一個實作可以(MAY)選擇僅提供有效資料元素但這是可選的(OPTIONAL). 用戶端不應該(SHOULD NOT)濫用發送不符合schema的資料的能力, 並且應該(SHOULD)忽略接收到的XML流中任何和schema不一致的元素或屬性值. XML流和節的有效性確認是可選的(OPTIONAL),並且在這裏提到的schemas僅用於描述的用途.
________________________________________
11.4. 文本聲明的包含 (Inclusion of Text Declaration)(?)
實現應該(SHOULD)在發送一個流標頭資訊之前發送一個文本聲明. 應用程式必須(MUST)遵守[XML]中關於環境(那裏對文本聲明做了規定)的規則.
________________________________________
11.5. 字元編碼 (Character Encoding)
Implementations MUST support the UTF-8 (RFC 3629 [UTF 8]) transformation of Universal Character Set (ISO/IEC 10646-1 [UCS2]) characters, as required by RFC 2277 [CHARSET]. Implementations MUST NOT attempt to use any other encoding.
實作必須(MUST)支援通用字元集Universal Character Set (ISO/IEC 10646-1 [UCS2])字元到UTF-8(RFC 3629 [UTF-8])的轉換, 必須符合 RFC 2277 [CHARSET]. 實作不能(MUST NOT)試圖使用任何其他的編碼.
@UTF-8為Unicode編碼的一種轉換格式,UCS2 為Unicode 雙字節編碼規範
________________________________________
12. 核心的相容性要求 (Core Compliance Requirements)
本章總結了可擴展的消息和出席資訊協定中的某些方面,為了實施的相容性,它們必須(MUST)被伺服器和用戶端支援,當然協定的其他方面也應該(SHOULD)被支持. 為了相容的目的, 我們在核心協議和即時消息協定之間劃了一個級別. 在本章中定義了所有伺服器和用戶端的相容性要求; 即時消息伺服器和用戶端的相容性要求在XMPP-IM的相關章節中定義.
________________________________________
12.1. 伺服器 (Servers)
除了所有已定義的關於安全, XML使用, 和國際化的要求之外, 一個伺服器還必須(MUST)支援以下核心協定以保證相容性:
o 在地址中應用[STRINGPREP] 的 [NAMEPREP], Nodeprep (附錄 A),和 Resourceprep (附錄 B) profiles (包括確保域ID是[IDNA]中定義的國際化功能變數名稱)
o XML流(第四章), 包括Use of TLS(第五章), Use of SASL(第六章), 和Resource Binding (第七章)
o 三個在stanza semantics(第九章第二節)中已定義的節類型(即,<message/>, <presence/>, 和<iq/>)的基本語義
o 生成錯誤的語法及相關的流, TLS, SASL, 和 XML節的語義
另外, 一個伺服器可以(MAY)支援以下核心協定:
o 伺服器回撥 (第八章)
@IDNA Internationalizing Domain Names in Applications => http://www.ietf.org/rfc/rfc3490.txt
為國際域名應用協定,將域名to ascii and to unicode的程序來達到國際化域名的應用
@STRINGPREP => rfc3454 http://www.ietf.org/rfc/rfc3454.txt
是字串辨識(比對)的標準協定,規範內容大概如下:
1. 字型的運用
2. 對於input and output字元的使用
3. 字串比對
4. unicode的標準化
5. 禁止的字元
6. 字串雙向性的問題
@NAMEPREP => rfc3491 http://www.ietf.org/rfc/rfc3491.txt
是使用在domain name system 上的協定
主要是儘可能將IDN在經過對照(Mapping)、正規化(Normalization)、禁止檢查(Prohibition)的處理後,得到一個符合IDN規格的形式。
________________________________________
12.2. 用戶端 (Clients)
一個用戶端必須(MUST)支援以下核心協定以滿足相容性:
o XML流(第四章), 包括Use of TLS(第五章), Use of SASL(第六章), 和Resource Binding (第七章)
o 三個在stanza semantics(第九章第二節)中已定義的節類型(即,<message/>, <presence/>, 和<iq/>)的基本語義
o 處理(並且, 如果可能, 生成) 錯誤的語法及相關的流, TLS, SASL, 和 XML節的語義
另外, 一個用戶端應該(SHOULD)支援以下核心協定:
o 地址的生成應用[STRINGPREP] 的 [NAMEPREP], Nodeprep (附錄 A),和 Resourceprep (附錄 B) profiles
________________________________________
13. 國際化事項 (Internationalization Considerations)
XML流在Character Encoding(第十一章第五節)中定義為必須(MUST)被編碼成UTF-8. 在Stream Attributes(第四章第四節)中特別定義了, 一個XML流應該(SHOULD)包含一個'xml:lang'屬性,它被認為是通過這個用於人類用戶解讀的流發送的任何XML字元資料的預設語言. 在 xml:lang (第九章第一節第五小節)特別定義了, 如果一個XML節是用來給人類用戶解讀,這個節應該(SHOULD)包含一個'xml:lang'屬性. 伺服器在為連接的實體路由或遞送節的時候應該(SHOULD)應用預設的'xml:lang'屬性, 並且不能(MUST NOT)修改或刪除它從其他實體收到的節的'xml:lang'屬性.
<message from='juliet@example.com' to='romeo@example.net' xml:lang='en'>
<body>Art thou not Romeo, and a Montague?</body>
</message> en 英語 zh華語 ja日語 …
________________________________________
14. 安全性事項 (Security Considerations)
________________________________________
14.1. 高安全性 (High Security)
為了XMPP通信的目的(用戶端-伺服器 和 伺服器-伺服器), "高安全性"條款談的是相互驗證和完整性檢查安全性技術的使用; 特別是, 當使用基於憑證的驗證來提供高安全性, 應該( SHOULD)建立一個帶外的信任鏈,儘管一個共用簽名憑證可能允許以前不知道的憑證在帶內建立信任關係. 參見以下第十四章第二節關於憑證確認程式. 實施必須(MUST)支持高安全性. 服務提供者應該(SHOULD)基於本地安全策略使用高安全性. ________________________________________
14.2. 憑證確認 (Certificate Validation) (?)
當一個XMPP點和另一個XMPP點安全的地通信, 它必須(MUST)確認對方終端的憑證.有三種可能的情況:
情形 #1: 點包含一個終端實體憑證,以根憑證的憑證鏈中一環出現(見[X509]中的第六章第一節).
情形 #2: 點的憑證由一個對方不知道的憑證授權.
情形 #3: 點的憑證由自己簽名.
在情形#1, 確認方必須(MUST)做以下兩點之一:
1. 根據[X509]的規則確認對方憑證.然後憑證應該(SHOULD)被對方接下來在[HTTP-TLS]中描述的規則反向確認預期的身份。但如果"xmpp"是subjectAltName擴展類型,則必須(MUST)使用憑證中的顯示的身份。如果這兩項檢查之一失敗,用戶導向的用戶端必須(MUST)通知用戶(用戶端可以(MAY)給用戶機會繼續連接)或以一個壞憑證的錯誤終止連接。自動用戶端應該(SHOULD)終止連接(以一個壞憑證錯誤)並在適當的日誌中記錄這個錯誤。自動用戶端可以(MAY)提供一個配置設置成禁止檢查,但同時必須(MUST)提供一個啟動檢查的配置。
2. 點應該(SHOULD)出示憑證給一個用戶用於批准,包括完整的憑證鏈.點必須(MUST)緩存這個憑證(或一些其他不會忘記的表達方式比如一個哈希值).在將來的連接中,點必須(MUST)展示相同的憑證並且如果改變了憑證必須(MUST)通知用戶.
在情形#2 和情形#3, 實現應該(SHOULD)執行上述第二條.
________________________________________
14.3. 用戶端-伺服器通信 (Client-to-Server Communications)
一個相容的用戶端實現必須(MUST)支持TLS和SASL用於連接到伺服器.
用於加密XML流的TLS協議(在 Use of TLS(第五章)定義)提供可信的機制幫助確保機密性和實體之間資料交換的完整性.
用於驗證XML流的SASL協定(在 Use of SASL(第六章)定義)提供可靠的機制用於確認一個連接到伺服器的用戶端確實是它自己所聲明的那個用戶端.
伺服器宣稱的DNS主機名被解析之前,用戶端-伺服器通信不能(MUST NOT)繼續進行。應該首先嘗試解析[SRV]記錄,其服務名為"xmpp-client",協議名為"tcp",整個資源記錄類似"_xmpp-client._tcp.example.com."(使用字元"xmpp-client"表示服務ID是經過IANA註冊).如果SRV查找失敗,退而求其次,將查找一個正規的IPv4/IPv6位址記錄來決定IP位址,使用"xmpp-client"埠5222,這個埠是在IANA註冊了的。
用戶端的IP位址和訪問方法不能(MUST NOT)被伺服器公開, 也不能被被任何原始伺服器之外的伺服器索取。這幫助保護用戶端的伺服器避免受到直接攻擊(譯者注:似乎應該是客戶避免受到直接攻擊,但原文如此)或被第三方知道它的身份。
@IANA => Internet Assigned Numbers Authority 網際網路號分配機構。負責對IP位址分配規劃以及對TCP/UDP公共服務的埠定義。
________________________________________
14.4. 伺服器-伺服器通信 (Server-to-Server Communications)
一個相容的伺服器實現必須(MUST)支持TLS和SASL,用於域間的通信.因為歷史原因,一個相容的實施也應該(SHOULD)支持伺服器回撥(第八章).
因為服務提供者是一個策略問題,對於任何給定域和其他域的通信中,它是可選的(OPTIONAL),伺服器之間的通信可以(MAY)被任何特定部署的管理員禁止。如果一個特殊的域允許域間的通信,它應該(SHOULD)允許高安全性。
管理員可能想在伺服器間使用SASL來通信,以確保雙方的驗證和保密性(比如在機構的私有網路).相容實施應該(SHOULD)為這個目的支援SASL.
伺服器宣稱的DNS主機名被解析之前,伺服器-伺服器通信不能(MUST NOT)繼續進行。應該首先嘗試解析[SRV]記錄,其服務名為"xmpp-server",協議名為"tcp",整個資源記錄類似"_xmpp-server._tcp.example.com."(使用字元"xmpp-server"表示服務ID是經過IANA註冊的,注意要用"xmpp-server"取代以前用的"jabber",因為以前的用法不符合[SRV]標準;希望保持向後相容的實現可以繼續查找或應答"jabber"服務ID).如果SRV查找失敗,退而求其次,將查找一個正規的IPv4/IPv6位址記錄來決定IP位址,使用"xmpp-server"埠5269,這個埠是在IANA註冊了的。
伺服器回撥防止域欺騙,從而使得偽造XML節更為困難.它和SASL和TLS不一樣,它不是一個用於驗證、安全或加密伺服器之間的流的機制, 所以只是伺服器身份的微弱確認而已。而且除非它使用了DNSSec [DNSSEC]否則它容易受到DNS中毒攻擊,即使DNS資訊是正確的,如果攻擊者劫持了遠程域,回撥也不能防止它的攻擊.需要健壯的安全性的域應該(SHOULD)使用TLS和SASL.如果伺服器間的驗證使用了SASL,回撥就不應該(SHOULD NOT)使用了,因為它是多餘的.
________________________________________
14.5. 層的次序 (Order of Layers)
協議中的層的次序必須(MUST)如下堆積:
1. TCP
2. TLS
3. SASL
4. XMPP
這個次序的原理是,[TCP]是基於連接的層,被所有使用,所以處於最上層, [TLS]經常是由作業系統層提供,[SASL]經常由應用程式層提供, XMPP則是應用程式本身.
________________________________________
14.6. 缺乏綁定到TLS的SASL通道 (Lack of SASL Channel Binding to TLS)(?)
SASL構架不提供一個機制來綁定SASL驗證到一個提供機密性和完整性保護的安全層。這一通道綁定"channel binding"的缺乏阻礙了SASL確認低層安全性所綁定的源和目標終端和SASL所驗證的結果是否一致。如果終端不一致, 低層安全性不能被信任用來保護SASL驗證的實體之間的資料傳輸。在這種情況下,一個SASL安全層進行握手的時候應該有效的忽略低層安全性的存在。
________________________________________
14.7. 強制實現的技術 (Mandatory-to-Implement Technologies)
最低要求, 所有實現必須(MUST)支持以下機制:
對於驗證: SASL [DIGEST-MD5] 機制
對於機密性: TLS (使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密碼)
對於兩者: TLS 加 SASL EXTERNAL(使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密碼支援用戶端憑證)
________________________________________
14.8. 防火牆 (Firewalls)
使用XMPP通信通常是通過[TCP]連接到5222埠(用戶端-伺服器)或5269埠(伺服器-伺服器), 正如在IANA註冊的那樣(見 IANA Considerations (第十五章)). 使用這些廣為人知的埠允許管理員很容易的通過一般的防火牆來啟動或禁止XMPP活動.
________________________________________
14.9. 在SASL中使用base64
用戶端和伺服器都必須(MUST)確認在SASL協商中收到的任何[BASE64]資料. 一個實現必須(MUST)拒絕(不是忽略)任何非顯式允許base64字母的字串; 這有助於預防建立隱蔽通道洩漏資訊的行為。一個實現不能(MUST NOT)在非法輸入處中斷,如果那個('=')被包含在一些和最後的資料字元(如, "=AAA" or "BBBB=CCC")不同的東西裏面,必須(MUST)拒絕接下來的任何包含('=')的base64字元;這有助於防止對這個實現的緩存溢出攻擊和其他攻擊。Base 64編碼從外表看隱藏了容易辨認的資訊,例如密碼,但是不提供任何演算法機密性。Base 64編碼必須(MUST)按照RFC 3548[BASE64]第三章的定義執行。
________________________________________
14.10. Stringprep Profiles
為了處理域ID,XMPP使用了[STRINGPREP]中的[NAMEPREP] profile; 和Nameprep有關的安全性考慮, 參考[NAMEPREP]中的相關章節.
另外, XMPP 定義了兩個[STRINGPREP]的 profiles: 用於node identifiers的Nodeprep(附錄 A)和用於resource identifiers的Resourceprep(附錄 B).
Unicode 和 ISO/IEC 10646 集有許多字元看起來相似. 在許多時候, 安全協議的使用者可能看起來吻合,比如當比較信任的第三方的名字的時候. 因為沒有很多上下文的時候不可能映射看起來相似的字元,比如知道所用的字元集, stringprep不匹配相似字串,也不因為一些字串看起來像別的字串而禁止它們.
一個節點ID可能被作為一個實體的XMPP位址的一部分. 一個通常的用途是作為一個即時消息用戶的用戶名;另一個用途是作為一個多用途聊天室的名字; 很多其他種類的實體可能使用節點ID作為他們的位址的一部分。 這些服務的安全性可能會受到國際化節點ID的不同表達的威脅;例如, 一個用戶鍵入一個單獨的國際化的節點ID可能訪問了另一個用戶的帳號資訊, 或一個用戶可能獲得訪問一個受限的聊天室或服務的訪問許可權.
一個資源ID可能被作為一個實體的XMPP位址的一部分。一個通常的用戶是即時消息用戶所連接的資源(啟動的會話)的名字; 另一個是作為多用戶聊天室的某用戶的昵稱; 許多其他種類的實體可能使用資源ID作為他們位址的一部分.這些服務的安全性可能會受到國際化資源ID的不同表達的威脅;例如, 一個用戶可能嘗試以同一個名字初始化多個會話,或一個用戶可能發送一個消息給多用戶聊天室的一個人但實際上發給了另外一個人.
________________________________________
15. IANA 事項 (IANA Considerations)
________________________________________
15.1. 用於TLS資料的XML名字空間名
XMPP中用於TLS相關資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
@IETF =>internet enginner task force(負責網際網路標準研究及制定的組織)
URI: urn:ietf:params:xml:ns:xmpp-tls
________________________________________
15.2. 用於SASL資料的XML名字空間名
XMPP中用於SASL相關資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-sasl
<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
________________________________________
15.3. 用於流錯誤的XML名字空間名
XMPP中用於流相關錯誤的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-streams
<stream:error>
<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
</stream:error>
________________________________________
15.4. 用於資源綁定的XML名字空間名
XMPP中用於資源綁定的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-bind
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
________________________________________
15.5. 用於節錯誤的XML名字空間名
XMPP中用於節相關錯誤資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-stanzas
<stanza-kind to='sender' type='error'>
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'>OPTIONAL descriptive text</text>
</error>
</stanza-kind>
________________________________________
15.6. Nodeprep Profile of Stringprep
The Nodeprep profile of stringprep是在Nodeprep(附錄 A)定義的. IANA已經在stringprep profile registry中註冊了 Nodeprep.
________________________________________
15.7. Resourceprep Profile of Stringprep
The Resourceprep profile of stringprep是在Resourceprep(附錄 B)定義的. IANA已經在stringprep profile registry中註冊了Resourceprep.
________________________________________
15.8. GSSAPI 服務名
IANA已經註冊了 "xmpp" 作為一個 GSSAPI [GSS-API] 服務名, 在SASL Definition (第六章第三節)定義
@GSSAPI => Generic Security Services Application Programming Interface
通用安全服務應用程式程介面,它提供了一個通用的認證和安全訊息傳遞介面
http://www.faqs.org/rfcs/rfc2743.html
________________________________________
15.9. 埠號
IANA已經註冊了"xmpp-client" 和 "xmpp-server" 作為[TCP]埠號5222和5269的關鍵字.
這些埠應該(SHOULD)用於用戶端-伺服器 和 伺服器-伺服器通信,但它們的使用是可選的(OPTIONAL).
________________________________________
參考資料:
Punycode => http://www.ietf.org/rfc/rfc3492.txt
http://xn--fx5a34a.xn--fiqp7jnrek3iomgb4cbweev5d.tw/IDN.pdf
http://hi.baidu.com/jabber/blog/category/Jep
http://wiki.jabbercn.org/space/start
10. 伺服器處理XML節的規則 (Server Rules for Handling XML Stanzas)
相容的伺服器實做必須(MUST)確保兩個實體之間的XML節按次序處理. 除了按次序處理的需求之外, 每個伺服器實作將包含它自己的遞送樹"delivery tree"以處理它接收到的節.這個樹決定一個節是否需要路由到其他域, 在內部處理, 還是遞送到和一個已連接的節點相關的資源. 以下規則適用:
________________________________________
10.1. 沒有'to'地址 (No 'to' Address)
如果這個節沒有'to'屬性, 伺服器應該(SHOULD)為發送它的實體處理這個節. 因為所有從其他伺服器收到的節必須(MUST)擁有'to'屬性, 這個規則僅適用於從一個連接到這台伺服器的已註冊實體(如一個用戶端)收到的節,如果這個伺服器收到一個沒有'to'屬性的出席資訊節, 伺服器應該(SHOULD)向那些訂閱了這個發送實體的出席資訊的所有實體廣播它, 如果可能的話(即時消息和出席資訊應用程式中出席資訊廣播的語義定義在XMPP-IM). 如果伺服器接收到一個IQ類型為 "get" 或 "set" 且沒有'to'屬性的節並且它理解這個節的名字空間下的內容, 它必須(MUST)為這個發送實體處理節(在這裏"處理"的含義是由相關的名字空間的語義所決定的)或返回一個錯誤給發送實體.
#c to s 可以不用有 to 屬性 ,因為c to s 預設的 to 即是 server
#若是出席訊息<presence>沒有to屬性,即為廣播給所有訂閱者,rfc3921第五章說明如下:
(5.1.1初始化出席資訊 :
建立起一個會話之後, 一個用戶端應該(SHOULD)發送初始化出席資訊給伺服器來通知它的通信可用性.如這裏定義的, 初始化出席資訊節 (1) 必須(MUST) 不擁有'to'屬性(這表示它是由伺服器代替用戶端發送的廣播) 並且 (2) 必須(MUST) 不擁有'type'屬性).
________________________________________
10.2. 外部域 (Foreign Domain) (s to s)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身或其子域配置的主機名不匹配, 伺服器應該(SHOULD)路由這個節到外部域(取決於本地服務規定或安全策略關於域間通信的規定).有兩種可能的情況:
- 一個伺服器to伺服器之間的流已經存在於兩個域之間: 發送者的伺服器透過這個已存在的流為這個外部域路由(轉送)這個節到授權伺服器 - 兩個域之間沒有伺服器to伺服器之間的流: 發送者伺服器 (1) 解析這個外部域的主機名(定義在伺服器間的通信Server-to-Server Communications (第十四章第四節)), (2) 在兩個域之間進行伺服器到伺服器的流協商(定義在 Use of TLS (第五章) 和 Use of SASL (第六章)), 然後 (3) 通過這個新建的流為外部域路由(轉送)這個節到授權伺服器
如果路由(轉送)到接收者的伺服器不成功, 發送者的伺服器必須(MUST)返回一個錯誤給發送者; 如果接收者的伺服器聯繫上了但是從接收者的伺服器遞送到接收者不成功, 接收者伺服器必須(MUST)透過發送者的伺服器返回一個錯誤給發送者.
________________________________________
10.3. 子域 (Subdomain) (?)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名的一個子功能變數名稱匹配,伺服器必須(MUST)自己處理這個節或路由這個節到專門負責這個子域的特定服務(如果子域被配置了),或者返回一個錯誤給發送者(如果子域沒有配置).
________________________________________
10.4. 純粹的域或特定的資源 (Mere Domain or Specific Resource)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名本身匹配,並且'to'屬性中的JID類型是<domain> 或 <domain/resource>, 伺服器(或其中定義的資源)必須(MUST)根據節的類型適當的處理這個節或返回一個錯誤節給發送者.
________________________________________
10.5. 同一域中的節點 (Node in Same Domain)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名本身匹配,並且'to'屬性中的JID類型是<node@domain> 或 <node@domain/resource>, 伺服器應該(SHOULD)遞送這個節到'to'屬性中的JID所指明的預定的接收者. 以下規則適用:
1. 如果這個JID包含一個資源ID(例如, 格式是<node@domain/resource>)並且存在一個連接的資源符合這個全JID, 接收者伺服器應該(SHOULD)遞送這個節給正確符合這個資源ID的流或會話.
2. 如果這個JID包含一個資源ID(例如, 格式是<node@domain/resource>)並且不存在一個連接的資源符合這個全JID, 接收者伺服器應該(SHOULD)返回一個<service-unavailable/> 節錯誤給發送者.
3. 如果這個JID的格式是<node@domain>並且存在至少一個此節點的連接資源, 接收伺服器應該( SHOULD)遞送這個節給至少其中一個已連接的資源, 依據應用程式定義的規則(一系列即時消息和出席資訊應用程式的遞送規則定義在XMPP-IM).
@Rfc3921第11章 伺服器處理XML節的規則有詳細的說明如下:
如果JID的格式是<user@domain>並且這個用戶至少有一個可用的資源, 接收者的伺服器必須(MUST)遵守以下規則:
1. 對於消息(message)節, 伺服器應該(SHOULD)遞送這個節給高優先順序的可用資源(如果這個資源沒有提供<priority/>元素的值, 伺服器應該(SHOULD)認為它提供的值為零). 如果兩個或更多的可用資源有相同的優先順序, 伺服器可以(MAY)使用一些其他的規則(例如, 最近的連接時間, 最近的活動時間, 或由一些<show/>值的層次所定義的最高的可用性) 來從它們中間選擇,或可以(MAY)遞送這個消息到所有這些資源. 無論如何, 伺服器不能(MUST NOT)遞送這個節到一個優先順序為負數的可用資源; 如果唯一的一個可用資源的優先順序是負數, 伺服器應該(SHOULD)當成沒有可用資源一樣處理這個消息(定義在後面). 另外, 伺服器不能(MUST NOT)重寫'to'屬性(換言之, 它必須(MUST)讓它保持<user@domain>而不是改成<user@domain/resource>).
2. 對於類型不是"probe"(探測)的出席資訊節, 伺服器必須(MUST)遞送這個節給所有可用的資源;對於出席資訊調查, 伺服器應該(SHOULD)基於定義在 出席資訊調查Presence Probes (第五章第一節第三小節)的規則來應答. 另外, 伺服器不能(MUST NOT)重寫'to'屬性(換言之, 它必須(MUST)保持<user@domain>而不是改為<user@domain/resource>).
3. 對於IQ節, 伺服器本身必須(MUST)代替用戶應答一個IQ result或一個IQ error, 並且不能(MUST NOT)遞送這個IQ節給任何可用的資源. 具體來說, 如果合格的名字空間的語義定義了一個伺服器可以提供的應答, 伺服器必須(MUST)代替用戶應答這個節; 如果沒有, 伺服器必須(MUST)應答一個<service-unavailable/>節錯誤.
<presence from='juliet@example.com/balcony'>
<priority>13</priority> => whose value is an integer between -128 and +127. rfc3921 2.2.2.3
</presence>
<presence from='juliet@example.com/balcony'>
<show>away</show> => chat dnd xa rfc3921 2.2.2.1
</presence>
________________________________________
11. XMPP中的XML用法 (XML Usage within XMPP)
________________________________________
11.1. 限制 (Restrictions)
XMPP是一個簡單的流式XML元素的專用協定用於接近即時地交換結構化資訊. 因為XMPP不需要任意的解析和所有的XML文檔, 所以XMPP不需要支援[XML]的所有功能. 特殊的, 適用以下限制.
關於XML生成, 一個XMPP實作不能(MUST NOT)在XML流中注入以下任何東西:
o 注釋 (第二章第五節[XML]) ,如 <!--XXX-->
o 處理指令(第二章第六節 同上) , target content parent
o 內部或外部的 DTD 子集 (第二章第八節 同上)
o 內部或外部的實體參考 (第四章第二節 同上) 除了預定實體以外(第四章第六節 同上)
o 字元資料或屬性值包含和預定實體列表中吻合的未逸出的unescaped字元(第四章第六節 同上); 這些字元必須(MUST)逸出 ,如 & < > …
關於XML處理, 如果一個XMPP實現接收到這些受限的XML資料,它必須(MUST)忽略這些資料.
________________________________________
11.2. XML 命名空間的名字和前綴詞 (XML Namespace Names and Prefixes)
XML名字空間[XML-NAMES]為所有XMPP相容的XML建立資料所有權的嚴格界限. 這個名字空間的基本功能是把結構上混合在一起的XML元素區分出不同的辭彙. 確保XMPP相容的XML有名字空間的感知能力使得任何允許的XML可以被結構化的混合到任何XMPP資料元素中. XML名字空間的名字和首碼的規則在下一小節中.
________________________________________
11.2.1. 流命名空間 (Streams Namespace)
在所有的XML流頭中必須聲明一個流名字空間. 流名字空間必須(MUST)是 'http://etherx.jabber.org/streams'. 元素名<stream/>和它的<features/>和<error/>子元素必須(MUST)在所有實例中符合這個流名字空間首碼. 一個實作應該(SHOULD)只為這些元素生成'stream:'首碼, 並且由於歷史原因可以(MAY)只接受'stream:'首碼.
________________________________________
11.2.2. 預設命名空間 (Default Namespace)
在所有的XML流中必須聲明一個預設的流名字空間用於定義允許的流根元素的一級子元素. 這個名字空間聲明對於初始化流和應答流必須(MUST)是相同的使得雙方的流都是合格一致的. 預設的名字空間聲明適用於流和所有在流中發送的節(除非由流名字空間或回撥名字空間的首碼顯式的符合另一個名字空間).
一個伺服器實現必須(MUST)支持以下兩個預設名字空間(由於歷史原因, 一些實現可能(MAY)只支持這兩個預設名字空間):
o jabber:client -- 當流用於用戶端和伺服器的通信時聲明這個預設名字空間
o jabber:server -- 當流用於兩個伺服器間的通信時聲明這個預設名字空間
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
一個用戶端實作必須(MUST)支持'jabber:client'預設名字空間,並且由於歷史原因可以(MAY)只支持這個預設名字空間.
如果預設名字空間是'jabber:client'或'jabber:server',一個實作不能(MUST NOT)在這個名字空間下為元素生成名字空間前綴詞. 一個實作不應該(SHOULD NOT)按照元素的內容(可能和流相反)生成不同於'jabber:client'和'jabber:server'名字空間前綴詞.
注意: 'jabber:client' 和 'jabber:server' 名字空間接近於相同但是用於不同的上下文(用戶端伺服器通信用'jabber:client' 而伺服器間通信用'jabber:server'). 這兩者之間僅有的不同在於在'jabber:client'中被發送的節中'to'和'from'屬性是可選的(OPTIONAL),而在'jabber:server'中被發送的節中它們是必需的(REQUIRED). 如果相容的實施接受一個符合'jabber:client'或'jabber:server'名字空間的流, 它必須(MUST)支援通用屬性(第九章第一節)和三個核心節類型(message, presence, 和IQ)的基本語義(第九章第二節).
________________________________________
11.2.3. 回撥名字空間 (Dialback Namespace)(?)
所有用於伺服器回撥的(第八章)元素都必須聲明一個回撥名字空間. 回撥名字空間的名字必須(MUST)是'jabber:server:dialback'. 所有符合此名字空間的元素必須(MUST)有首碼. 一個實現應該(SHOULD)只為這些元素生成'db:'首碼並且只可以(MAY)接受'db:'首碼.
________________________________________
11.3. 確認 (Validation)
除了注意'jabber:server'名字空間中關於節中'to'和'from'位址的規定,一個伺服器不需要為轉發到用戶端或其他伺服器負責檢查XML元素;一個實作可以(MAY)選擇僅提供有效資料元素但這是可選的(OPTIONAL). 用戶端不應該(SHOULD NOT)濫用發送不符合schema的資料的能力, 並且應該(SHOULD)忽略接收到的XML流中任何和schema不一致的元素或屬性值. XML流和節的有效性確認是可選的(OPTIONAL),並且在這裏提到的schemas僅用於描述的用途.
________________________________________
11.4. 文本聲明的包含 (Inclusion of Text Declaration)(?)
實現應該(SHOULD)在發送一個流標頭資訊之前發送一個文本聲明. 應用程式必須(MUST)遵守[XML]中關於環境(那裏對文本聲明做了規定)的規則.
________________________________________
11.5. 字元編碼 (Character Encoding)
Implementations MUST support the UTF-8 (RFC 3629 [UTF 8]) transformation of Universal Character Set (ISO/IEC 10646-1 [UCS2]) characters, as required by RFC 2277 [CHARSET]. Implementations MUST NOT attempt to use any other encoding.
實作必須(MUST)支援通用字元集Universal Character Set (ISO/IEC 10646-1 [UCS2])字元到UTF-8(RFC 3629 [UTF-8])的轉換, 必須符合 RFC 2277 [CHARSET]. 實作不能(MUST NOT)試圖使用任何其他的編碼.
@UTF-8為Unicode編碼的一種轉換格式,UCS2 為Unicode 雙字節編碼規範
________________________________________
12. 核心的相容性要求 (Core Compliance Requirements)
本章總結了可擴展的消息和出席資訊協定中的某些方面,為了實施的相容性,它們必須(MUST)被伺服器和用戶端支援,當然協定的其他方面也應該(SHOULD)被支持. 為了相容的目的, 我們在核心協議和即時消息協定之間劃了一個級別. 在本章中定義了所有伺服器和用戶端的相容性要求; 即時消息伺服器和用戶端的相容性要求在XMPP-IM的相關章節中定義.
________________________________________
12.1. 伺服器 (Servers)
除了所有已定義的關於安全, XML使用, 和國際化的要求之外, 一個伺服器還必須(MUST)支援以下核心協定以保證相容性:
o 在地址中應用[STRINGPREP] 的 [NAMEPREP], Nodeprep (附錄 A),和 Resourceprep (附錄 B) profiles (包括確保域ID是[IDNA]中定義的國際化功能變數名稱)
o XML流(第四章), 包括Use of TLS(第五章), Use of SASL(第六章), 和Resource Binding (第七章)
o 三個在stanza semantics(第九章第二節)中已定義的節類型(即,<message/>, <presence/>, 和<iq/>)的基本語義
o 生成錯誤的語法及相關的流, TLS, SASL, 和 XML節的語義
另外, 一個伺服器可以(MAY)支援以下核心協定:
o 伺服器回撥 (第八章)
@IDNA Internationalizing Domain Names in Applications => http://www.ietf.org/rfc/rfc3490.txt
為國際域名應用協定,將域名to ascii and to unicode的程序來達到國際化域名的應用
@STRINGPREP => rfc3454 http://www.ietf.org/rfc/rfc3454.txt
是字串辨識(比對)的標準協定,規範內容大概如下:
1. 字型的運用
2. 對於input and output字元的使用
3. 字串比對
4. unicode的標準化
5. 禁止的字元
6. 字串雙向性的問題
@NAMEPREP => rfc3491 http://www.ietf.org/rfc/rfc3491.txt
是使用在domain name system 上的協定
主要是儘可能將IDN在經過對照(Mapping)、正規化(Normalization)、禁止檢查(Prohibition)的處理後,得到一個符合IDN規格的形式。
________________________________________
12.2. 用戶端 (Clients)
一個用戶端必須(MUST)支援以下核心協定以滿足相容性:
o XML流(第四章), 包括Use of TLS(第五章), Use of SASL(第六章), 和Resource Binding (第七章)
o 三個在stanza semantics(第九章第二節)中已定義的節類型(即,<message/>, <presence/>, 和<iq/>)的基本語義
o 處理(並且, 如果可能, 生成) 錯誤的語法及相關的流, TLS, SASL, 和 XML節的語義
另外, 一個用戶端應該(SHOULD)支援以下核心協定:
o 地址的生成應用[STRINGPREP] 的 [NAMEPREP], Nodeprep (附錄 A),和 Resourceprep (附錄 B) profiles
________________________________________
13. 國際化事項 (Internationalization Considerations)
XML流在Character Encoding(第十一章第五節)中定義為必須(MUST)被編碼成UTF-8. 在Stream Attributes(第四章第四節)中特別定義了, 一個XML流應該(SHOULD)包含一個'xml:lang'屬性,它被認為是通過這個用於人類用戶解讀的流發送的任何XML字元資料的預設語言. 在 xml:lang (第九章第一節第五小節)特別定義了, 如果一個XML節是用來給人類用戶解讀,這個節應該(SHOULD)包含一個'xml:lang'屬性. 伺服器在為連接的實體路由或遞送節的時候應該(SHOULD)應用預設的'xml:lang'屬性, 並且不能(MUST NOT)修改或刪除它從其他實體收到的節的'xml:lang'屬性.
<message from='juliet@example.com' to='romeo@example.net' xml:lang='en'>
<body>Art thou not Romeo, and a Montague?</body>
</message> en 英語 zh華語 ja日語 …
________________________________________
14. 安全性事項 (Security Considerations)
________________________________________
14.1. 高安全性 (High Security)
為了XMPP通信的目的(用戶端-伺服器 和 伺服器-伺服器), "高安全性"條款談的是相互驗證和完整性檢查安全性技術的使用; 特別是, 當使用基於憑證的驗證來提供高安全性, 應該( SHOULD)建立一個帶外的信任鏈,儘管一個共用簽名憑證可能允許以前不知道的憑證在帶內建立信任關係. 參見以下第十四章第二節關於憑證確認程式. 實施必須(MUST)支持高安全性. 服務提供者應該(SHOULD)基於本地安全策略使用高安全性. ________________________________________
14.2. 憑證確認 (Certificate Validation) (?)
當一個XMPP點和另一個XMPP點安全的地通信, 它必須(MUST)確認對方終端的憑證.有三種可能的情況:
情形 #1: 點包含一個終端實體憑證,以根憑證的憑證鏈中一環出現(見[X509]中的第六章第一節).
情形 #2: 點的憑證由一個對方不知道的憑證授權.
情形 #3: 點的憑證由自己簽名.
在情形#1, 確認方必須(MUST)做以下兩點之一:
1. 根據[X509]的規則確認對方憑證.然後憑證應該(SHOULD)被對方接下來在[HTTP-TLS]中描述的規則反向確認預期的身份。但如果"xmpp"是subjectAltName擴展類型,則必須(MUST)使用憑證中的顯示的身份。如果這兩項檢查之一失敗,用戶導向的用戶端必須(MUST)通知用戶(用戶端可以(MAY)給用戶機會繼續連接)或以一個壞憑證的錯誤終止連接。自動用戶端應該(SHOULD)終止連接(以一個壞憑證錯誤)並在適當的日誌中記錄這個錯誤。自動用戶端可以(MAY)提供一個配置設置成禁止檢查,但同時必須(MUST)提供一個啟動檢查的配置。
2. 點應該(SHOULD)出示憑證給一個用戶用於批准,包括完整的憑證鏈.點必須(MUST)緩存這個憑證(或一些其他不會忘記的表達方式比如一個哈希值).在將來的連接中,點必須(MUST)展示相同的憑證並且如果改變了憑證必須(MUST)通知用戶.
在情形#2 和情形#3, 實現應該(SHOULD)執行上述第二條.
________________________________________
14.3. 用戶端-伺服器通信 (Client-to-Server Communications)
一個相容的用戶端實現必須(MUST)支持TLS和SASL用於連接到伺服器.
用於加密XML流的TLS協議(在 Use of TLS(第五章)定義)提供可信的機制幫助確保機密性和實體之間資料交換的完整性.
用於驗證XML流的SASL協定(在 Use of SASL(第六章)定義)提供可靠的機制用於確認一個連接到伺服器的用戶端確實是它自己所聲明的那個用戶端.
伺服器宣稱的DNS主機名被解析之前,用戶端-伺服器通信不能(MUST NOT)繼續進行。應該首先嘗試解析[SRV]記錄,其服務名為"xmpp-client",協議名為"tcp",整個資源記錄類似"_xmpp-client._tcp.example.com."(使用字元"xmpp-client"表示服務ID是經過IANA註冊).如果SRV查找失敗,退而求其次,將查找一個正規的IPv4/IPv6位址記錄來決定IP位址,使用"xmpp-client"埠5222,這個埠是在IANA註冊了的。
用戶端的IP位址和訪問方法不能(MUST NOT)被伺服器公開, 也不能被被任何原始伺服器之外的伺服器索取。這幫助保護用戶端的伺服器避免受到直接攻擊(譯者注:似乎應該是客戶避免受到直接攻擊,但原文如此)或被第三方知道它的身份。
@IANA => Internet Assigned Numbers Authority 網際網路號分配機構。負責對IP位址分配規劃以及對TCP/UDP公共服務的埠定義。
________________________________________
14.4. 伺服器-伺服器通信 (Server-to-Server Communications)
一個相容的伺服器實現必須(MUST)支持TLS和SASL,用於域間的通信.因為歷史原因,一個相容的實施也應該(SHOULD)支持伺服器回撥(第八章).
因為服務提供者是一個策略問題,對於任何給定域和其他域的通信中,它是可選的(OPTIONAL),伺服器之間的通信可以(MAY)被任何特定部署的管理員禁止。如果一個特殊的域允許域間的通信,它應該(SHOULD)允許高安全性。
管理員可能想在伺服器間使用SASL來通信,以確保雙方的驗證和保密性(比如在機構的私有網路).相容實施應該(SHOULD)為這個目的支援SASL.
伺服器宣稱的DNS主機名被解析之前,伺服器-伺服器通信不能(MUST NOT)繼續進行。應該首先嘗試解析[SRV]記錄,其服務名為"xmpp-server",協議名為"tcp",整個資源記錄類似"_xmpp-server._tcp.example.com."(使用字元"xmpp-server"表示服務ID是經過IANA註冊的,注意要用"xmpp-server"取代以前用的"jabber",因為以前的用法不符合[SRV]標準;希望保持向後相容的實現可以繼續查找或應答"jabber"服務ID).如果SRV查找失敗,退而求其次,將查找一個正規的IPv4/IPv6位址記錄來決定IP位址,使用"xmpp-server"埠5269,這個埠是在IANA註冊了的。
伺服器回撥防止域欺騙,從而使得偽造XML節更為困難.它和SASL和TLS不一樣,它不是一個用於驗證、安全或加密伺服器之間的流的機制, 所以只是伺服器身份的微弱確認而已。而且除非它使用了DNSSec [DNSSEC]否則它容易受到DNS中毒攻擊,即使DNS資訊是正確的,如果攻擊者劫持了遠程域,回撥也不能防止它的攻擊.需要健壯的安全性的域應該(SHOULD)使用TLS和SASL.如果伺服器間的驗證使用了SASL,回撥就不應該(SHOULD NOT)使用了,因為它是多餘的.
________________________________________
14.5. 層的次序 (Order of Layers)
協議中的層的次序必須(MUST)如下堆積:
1. TCP
2. TLS
3. SASL
4. XMPP
這個次序的原理是,[TCP]是基於連接的層,被所有使用,所以處於最上層, [TLS]經常是由作業系統層提供,[SASL]經常由應用程式層提供, XMPP則是應用程式本身.
________________________________________
14.6. 缺乏綁定到TLS的SASL通道 (Lack of SASL Channel Binding to TLS)(?)
SASL構架不提供一個機制來綁定SASL驗證到一個提供機密性和完整性保護的安全層。這一通道綁定"channel binding"的缺乏阻礙了SASL確認低層安全性所綁定的源和目標終端和SASL所驗證的結果是否一致。如果終端不一致, 低層安全性不能被信任用來保護SASL驗證的實體之間的資料傳輸。在這種情況下,一個SASL安全層進行握手的時候應該有效的忽略低層安全性的存在。
________________________________________
14.7. 強制實現的技術 (Mandatory-to-Implement Technologies)
最低要求, 所有實現必須(MUST)支持以下機制:
對於驗證: SASL [DIGEST-MD5] 機制
對於機密性: TLS (使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密碼)
對於兩者: TLS 加 SASL EXTERNAL(使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密碼支援用戶端憑證)
________________________________________
14.8. 防火牆 (Firewalls)
使用XMPP通信通常是通過[TCP]連接到5222埠(用戶端-伺服器)或5269埠(伺服器-伺服器), 正如在IANA註冊的那樣(見 IANA Considerations (第十五章)). 使用這些廣為人知的埠允許管理員很容易的通過一般的防火牆來啟動或禁止XMPP活動.
________________________________________
14.9. 在SASL中使用base64
用戶端和伺服器都必須(MUST)確認在SASL協商中收到的任何[BASE64]資料. 一個實現必須(MUST)拒絕(不是忽略)任何非顯式允許base64字母的字串; 這有助於預防建立隱蔽通道洩漏資訊的行為。一個實現不能(MUST NOT)在非法輸入處中斷,如果那個('=')被包含在一些和最後的資料字元(如, "=AAA" or "BBBB=CCC")不同的東西裏面,必須(MUST)拒絕接下來的任何包含('=')的base64字元;這有助於防止對這個實現的緩存溢出攻擊和其他攻擊。Base 64編碼從外表看隱藏了容易辨認的資訊,例如密碼,但是不提供任何演算法機密性。Base 64編碼必須(MUST)按照RFC 3548[BASE64]第三章的定義執行。
________________________________________
14.10. Stringprep Profiles
為了處理域ID,XMPP使用了[STRINGPREP]中的[NAMEPREP] profile; 和Nameprep有關的安全性考慮, 參考[NAMEPREP]中的相關章節.
另外, XMPP 定義了兩個[STRINGPREP]的 profiles: 用於node identifiers的Nodeprep(附錄 A)和用於resource identifiers的Resourceprep(附錄 B).
Unicode 和 ISO/IEC 10646 集有許多字元看起來相似. 在許多時候, 安全協議的使用者可能看起來吻合,比如當比較信任的第三方的名字的時候. 因為沒有很多上下文的時候不可能映射看起來相似的字元,比如知道所用的字元集, stringprep不匹配相似字串,也不因為一些字串看起來像別的字串而禁止它們.
一個節點ID可能被作為一個實體的XMPP位址的一部分. 一個通常的用途是作為一個即時消息用戶的用戶名;另一個用途是作為一個多用途聊天室的名字; 很多其他種類的實體可能使用節點ID作為他們的位址的一部分。 這些服務的安全性可能會受到國際化節點ID的不同表達的威脅;例如, 一個用戶鍵入一個單獨的國際化的節點ID可能訪問了另一個用戶的帳號資訊, 或一個用戶可能獲得訪問一個受限的聊天室或服務的訪問許可權.
一個資源ID可能被作為一個實體的XMPP位址的一部分。一個通常的用戶是即時消息用戶所連接的資源(啟動的會話)的名字; 另一個是作為多用戶聊天室的某用戶的昵稱; 許多其他種類的實體可能使用資源ID作為他們位址的一部分.這些服務的安全性可能會受到國際化資源ID的不同表達的威脅;例如, 一個用戶可能嘗試以同一個名字初始化多個會話,或一個用戶可能發送一個消息給多用戶聊天室的一個人但實際上發給了另外一個人.
________________________________________
15. IANA 事項 (IANA Considerations)
________________________________________
15.1. 用於TLS資料的XML名字空間名
XMPP中用於TLS相關資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
@IETF =>internet enginner task force(負責網際網路標準研究及制定的組織)
URI: urn:ietf:params:xml:ns:xmpp-tls
________________________________________
15.2. 用於SASL資料的XML名字空間名
XMPP中用於SASL相關資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-sasl
<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
________________________________________
15.3. 用於流錯誤的XML名字空間名
XMPP中用於流相關錯誤的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-streams
<stream:error>
<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
</stream:error>
________________________________________
15.4. 用於資源綁定的XML名字空間名
XMPP中用於資源綁定的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-bind
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
________________________________________
15.5. 用於節錯誤的XML名字空間名
XMPP中用於節相關錯誤資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-stanzas
<stanza-kind to='sender' type='error'>
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'>OPTIONAL descriptive text</text>
</error>
</stanza-kind>
________________________________________
15.6. Nodeprep Profile of Stringprep
The Nodeprep profile of stringprep是在Nodeprep(附錄 A)定義的. IANA已經在stringprep profile registry中註冊了 Nodeprep.
________________________________________
15.7. Resourceprep Profile of Stringprep
The Resourceprep profile of stringprep是在Resourceprep(附錄 B)定義的. IANA已經在stringprep profile registry中註冊了Resourceprep.
________________________________________
15.8. GSSAPI 服務名
IANA已經註冊了 "xmpp" 作為一個 GSSAPI [GSS-API] 服務名, 在SASL Definition (第六章第三節)定義
@GSSAPI => Generic Security Services Application Programming Interface
通用安全服務應用程式程介面,它提供了一個通用的認證和安全訊息傳遞介面
http://www.faqs.org/rfcs/rfc2743.html
________________________________________
15.9. 埠號
IANA已經註冊了"xmpp-client" 和 "xmpp-server" 作為[TCP]埠號5222和5269的關鍵字.
這些埠應該(SHOULD)用於用戶端-伺服器 和 伺服器-伺服器通信,但它們的使用是可選的(OPTIONAL).
________________________________________
參考資料:
Punycode => http://www.ietf.org/rfc/rfc3492.txt
http://xn--fx5a34a.xn--fiqp7jnrek3iomgb4cbweev5d.tw/IDN.pdf
http://hi.baidu.com/jabber/blog/category/Jep
http://wiki.jabbercn.org/space/start
Wednesday, December 5, 2007
Erlang/OTP R12B released
Major relese : otp_src_R12B-0
Build date : 2007-12-04
R12B-0 is a major new release of Erlang/OTP.
You can download the full source distribution from
http://www.erlang.org/download/otp_src_R12B-0.tar.gz
http://www.erlang.org/download/otp_src_R12B-0.readme (this file)
Note: To unpack the TAR archive you need a GNU TAR compatible program.
For installation instructions please read the README that is part of
the distribution.
The Windows binary distribution can be downloaded from
http://www.erlang.org/download/otp_win32_R12B-0.exe
On-line documentation can be found at http://www.erlang.org/doc/.
You can also download the complete HTML documentation or the Unix manual files
http://www.erlang.org/download/otp_doc_html_R12B-0.tar.gz
http://www.erlang.org/download/otp_doc_man_R12B-0.tar.gz
We also want to thank those that sent us patches, suggestions and bug
reports,
Build date : 2007-12-04
R12B-0 is a major new release of Erlang/OTP.
You can download the full source distribution from
http://www.erlang.org/download/otp_src_R12B-0.tar.gz
http://www.erlang.org/download/otp_src_R12B-0.readme (this file)
Note: To unpack the TAR archive you need a GNU TAR compatible program.
For installation instructions please read the README that is part of
the distribution.
The Windows binary distribution can be downloaded from
http://www.erlang.org/download/otp_win32_R12B-0.exe
On-line documentation can be found at http://www.erlang.org/doc/.
You can also download the complete HTML documentation or the Unix manual files
http://www.erlang.org/download/otp_doc_html_R12B-0.tar.gz
http://www.erlang.org/download/otp_doc_man_R12B-0.tar.gz
We also want to thank those that sent us patches, suggestions and bug
reports,
Friday, November 30, 2007
RFID智慧型護送系統建置計畫
昨天接獲資訊:
微程式資訊以專業技術與成功建置經驗獲得經濟部大型示範性計畫『RFID智慧型護送系統建置計畫』的支持,為醫療領域結合IT科技再跨出一步。 這可是一個將近兩千萬的專案阿,不過這事實上是一個XMPP 的應用,我們在XMPP 建置了一些訊息的交換邏輯,讓訊息在XMPP 上交易所產生的應用,業界這幾年對concurrent programming 需求殷切,主要是因為資訊系統跳了一個層次在看訊息傳遞這回事,當大量資訊需要即時 精確的被傳遞時,過去的那種multiprocess mutithread 不敷使用,一個動輒上萬的長時間連線交易,更需要像erlang 這類以concurrent programming 為觀點出發的語言,而這也同時是我會接觸functional language的主要原因
計畫相關聯結:
http://www.program.com.tw/news/news_071129.htm
http://blog.sina.com.tw/sandychang/article.php?pbgid=40436&entryid=575124
微程式資訊以專業技術與成功建置經驗獲得經濟部大型示範性計畫『RFID智慧型護送系統建置計畫』的支持,為醫療領域結合IT科技再跨出一步。 這可是一個將近兩千萬的專案阿,不過這事實上是一個XMPP 的應用,我們在XMPP 建置了一些訊息的交換邏輯,讓訊息在XMPP 上交易所產生的應用,業界這幾年對concurrent programming 需求殷切,主要是因為資訊系統跳了一個層次在看訊息傳遞這回事,當大量資訊需要即時 精確的被傳遞時,過去的那種multiprocess mutithread 不敷使用,一個動輒上萬的長時間連線交易,更需要像erlang 這類以concurrent programming 為觀點出發的語言,而這也同時是我會接觸functional language的主要原因
計畫相關聯結:
http://www.program.com.tw/news/news_071129.htm
http://blog.sina.com.tw/sandychang/article.php?pbgid=40436&entryid=575124
Tuesday, November 20, 2007
erlang 相關paper
http://www.it.uu.se/research/group/hipe/publications.shtml
內有相關於erlang 的論文 期刊 或是相關會議裡 提出的文章,其中這兩篇恰好是談到昨天提到的erlang bit syntax
http://user.it.uu.se/~kostis/Papers/JFP_06.pdf
Per Gustafsson and Konstantinos Sagonas
Efficient manipulation of binary data using pattern matching
In the Journal of Functional Programming, 16(1):35-74, January 2006
http://www.it.uu.se/research/group/hipe/papers/padl07.pdf
Per Gustafsson and Konstantinos Sagonas
Applications, Implementation and Performance Evaluation of Bit Stream Programming in Erlang In Proceedings of the Ninth International Symposium on Practical Aspects of Declarative Languages (PADL'07). To appear.
內有相關於erlang 的論文 期刊 或是相關會議裡 提出的文章,其中這兩篇恰好是談到昨天提到的erlang bit syntax
http://user.it.uu.se/~kostis/Papers/JFP_06.pdf
Per Gustafsson and Konstantinos Sagonas
Efficient manipulation of binary data using pattern matching
In the Journal of Functional Programming, 16(1):35-74, January 2006
http://www.it.uu.se/research/group/hipe/papers/padl07.pdf
Per Gustafsson and Konstantinos Sagonas
Applications, Implementation and Performance Evaluation of Bit Stream Programming in Erlang In Proceedings of the Ninth International Symposium on Practical Aspects of Declarative Languages (PADL'07). To appear.
Monday, November 19, 2007
Erlang Bit Syntax
Erlang Bit Syntax 看起來蠻強悍的,在erlang programming 裡提到一個 16-bit Colors 的例子:
<<這例子來自 erlang programming>>
1> Red = 2.
2
2> Green = 61.
61
3> Blue = 20.
20
4> Mem = <<Red:5, Green:6, Blue:5>>.
用在pattern matching也很直觀,比如:
<<Header2:8/binary,$\ ,Rest2/binary>> = <<"HTTP/1.1 200 OK\r\n">>.
不過;他目前還不支援regexp , 用起來有時會綁手綁腳,可能是還不太熟析? Bit Syntax 可以用在網路的封包解析,或是encode/decode某種檔案格式...目前;關於封包分析部分我也還在努力搞懂中
http://community.livejournal.com/en_dmitriid/5806.html
http://www.erlang.se/euc/07/papers/1700Gustafsson.pdf
這裡也有相關Erlang Bit Syntax的文章可參考
<<這例子來自 erlang programming>>
1> Red = 2.
2
2> Green = 61.
61
3> Blue = 20.
20
4> Mem = <<Red:5, Green:6, Blue:5>>.
用在pattern matching也很直觀,比如:
不過;他目前還不支援regexp , 用起來有時會綁手綁腳,可能是還不太熟析? Bit Syntax 可以用在網路的封包解析,或是encode/decode某種檔案格式...目前;關於封包分析部分我也還在努力搞懂中
http://community.livejournal.com/en_dmitriid/5806.html
Thursday, November 15, 2007
EUC '07 papers and slides
The EUC(Erlang/OTP User Conference 2007) papers and presentations are now available at http://www.erlang.se/euc/07
Tuesday, November 13, 2007
Wednesday, October 31, 2007
[微程式-技術研討會] 10月份研討會內容 主講人 vivian
1. 繼續分享xmpp的討會
3.5 地址的確認
在SASL(見第六章)握手之後(如果必要的話,也在資料綁定(見第七章)之後,正在接收信息的實體必須(MUST)確認初始實體的ID
對於服務器間的通信,在SASL握手時,如果沒有指明授權的ID,這個初始的實體應該(SHOULD)是經過認證實體(參見簡單認證和安全層協議[SASL]中的定義)授權的ID(見第六章)
對於客戶端和服務器的通信, 在SASL握手時, 如果沒有指明授權的ID, “純JID” (<node@domain>)應該(SHOULD)是經過認證實體(參見[SASL]中的定義)授權的ID, “全JID”(<node@domain/resource>)的資源ID部份應該(SHOULD)是由客戶端和服務器在資源綁定的時候商定的(參見第七章)
4.1 XML流 / XML節概覽
XML流(XML Stream)的定義: 一個XML流乃是一個容器, 包含了2個實體之間通過網絡交換XML元素, 一個XML流乃由一個<stream>標籤開始的(該標籤需包含適當的屬性及名字空間聲明), XML流的結束則是由</stream>標籤做為結束, 在XML流的整個生命週期中, 初始化它的實體可以通過流來發送大量的XML元素, 例如:TLS協議(第5章),SASL協議(第6章)或XML節(在這裡指的是符合預設名字空間的元素, 包括<message/>,<presence/>,<iq/>元素), “初始的XML流"由初始實體(通常是一個客戶端或服務器)和接收實體(通常為一個服務器)協議, 從接收實體來看, XML流就是那個初始實體對接收實體的 “會話”, 接收實體則必需回覆一個相同的應答流給初始實體
Ex:
<stream> è xml流開始
……………………………….
……………………………….
</stream> è xml流結束
XML節(XML Stanzas)的定義 : 一個XML節是一個實體通過XML流向另一個實體發送結構化信息中的一個離散語意單位, 一個XML節乃直接存於根元素<stream/>之下, 也就是說任何XML都是從一個XML流的下一級的某個OPEN標籤(如: <presence>)開始的, 並相對應到其CLOSE標籤(如: </presence>)做為結束, 一個XML節可以包含子元素(例如: 屬性, 元素, XML字符…..等資料)以表達整個完整的信息, 然而在定義的XML只限定於<message/>,</presence>,</iq>這3個元素, 其TLS / SASL / 服務器回撥所需發送的XML元素, 則不被視為一個XML節
Ex:
<stream> è xml流開始
………. è TLS協議 (可省略)
………. è SASL協議
<presence> è xml節開始
<show/> è xml節子元素
</presence> è xml節結束
<message> è xml節開始
<body/> è xml節子元素
</message> è xml節結束
……………………………….
……………………………….
</stream> è xml流結束
XML流與XML節圖示
---------------------------- <stream> ---------------------------- <presence> <show/> </presence> ---------------------------- <message to='foo'> <body/> </message> ---------------------------- <iq to='bar'> <query/> </iq> ---------------------------- … ---------------------------- </stream> ----------------------------
4.3 流的安全
在XMPP 1.0中, 對於流的安全性可使用TLS及SASL已做為初始實體(發送初始化流 Send Default XML Stream)與接收實體(發送應答流 Response XML Stream)已做為安全傳送機制, 若XML流在被真實驗證之前, 實體不該發送任何XML節(XML Stanza), 即使當一方於流被驗證之前發送了XML節, 另一方實體則不能接受這些節的傳入, 應該返回一個<not-authorized/>的錯誤訊息及終止當前雙方TCP連結的XML流
4.4 XML流(XML Stream)的屬性
屬性 初始實體(A) à 接收實體(B) 接收實體(B) à 初始實體(A)
to 接收實體(B)的主機名稱 可忽略
from 可省略 接收實體(B)的主機名稱
id 可省略 協議key值
xml:lang 預設語言 預設語言
version xmpp 1.0 xmpp 1.0
初始實體(A)可以為客戶端或伺服器端(Client à Server Or Server à Server) 初始實體(A) è 接收實體(B) <stream:stream
xmlns='jabber:client' Or xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>接收實體(B) è 初始實體(A) <stream:stream
xmlns='jabber:client' Or xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123' à 協議key值
from='B.Server.com'
version='1.0'>
5.1 TLS的使用概覽
XMPP包含了一個可讓XML流被防止篡改及偷聽的安全方法, 類似SSL的觀念
TLS使用原則需在SASL使用之前被使用, TLS可以在2個網域之間確保通信之間的安全, 其TLS使用方式步驟如下(初始實體[可以為客戶端(Client)或伺服器端(Server)]稱呼為 A, 接收實體[伺服器端(Server)]稱呼為 B)
1 . A透過TCP連接, 發送一OPEN之XML流信息(需包含版本這個屬性)給B【Client à Server】 <stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>
2. B也透過TCP連接, 發送一個XML流信息(需包含版本這個屬性)給A【Server à Client】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123' Or id='s2s_123'
from='B.Server.com'
version='1.0'>
3. B向A提議STARTTLS的範圍(包含version屬性), 包含驗證機制及其它流特性【Server à Client】<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'> è TLS協議
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> è SASL協議
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
4. A發出STARTTLS協議以通知B, 希望開始啟用 TLS保護XML流(XML Stream)
【Client à Server】<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
5. B發出<proceed/>或<failure/>元素做為回應, 回應<failure/>元素者終止XML流及TCP連接
【Server à Client】<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
OR <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream:stream>
6. TLS協議成功, 則A需重新發送一個新OPEN的XML流信息給B(不需先行發送一個</stream>, 因為A與B必需確保原來的流在TLS協議成功後才被關閉)
【Client à Server】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:Server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>
7. B由A接收到一個新的XML流, 也需重新發送一個新的XML流給A以做為應答, 其重新應答可包含可用特性但不可包含STARTTLS特性【Server à Client】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:Server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='c2s_234' Or id='s2s_234'
version='1.0'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
6.1 SASL概覽
XMPP提供一個可以驗證XML流(XML Stream)的方法, SASL(簡單驗證安全層), 需
注意的是SASL協議時, 在XML元素中所使用的任何資料皆需被編碼成BASE64(參考RFC3548第3章), 若在使用SASL驗證機制之前明訂需使用TLS,則接收實體不可在TLS協議之前提供可用的SASL驗證清單
7. 資源綁定
初始實體(A)在與和接收實體(B)完成SASL協議之後, 若初始實體(A)想要或需要綁定一個特定的資源到XML流上, 就需採用資源綁定協議, 而資源綁定協議只適用於 [客戶端] (初始實體(A)可以為客戶端或為伺服器), 客戶端必需擁有一個相關資源ID(可由接收實體(B)或初始實體(A)程序提供), 而在XML流上的地址是一個 [全JID] (<node@domain/resource>), 在SASL協議成功後接收實體(B)需回應一個新XML流(XML Stream), 接收實體(B)若需初始實體(A)綁定一個資源, 必需在新的XML流中包含一個空的<bind/>元素 接收實體(B) è 初始實體(A), B要求A需做binding resource機制 <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_345' from='B.Server.com' version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
初始實體(A)收到接收實體(B)發送的bind通知後, 初始實體(A)需發送一個 “set” 類型的IQ節(<iq/>)給接收實體(B)來綁定一個資源到xml流中
(A) . 初始實體(A)希望接收實體(B)生成一個資源ID, 則初始實體(A)可發送一個空的<bind/>元素的 “set” 類型IQ節(<iq/>) Client à Server <iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/> è 初始實體(A)希望由接收實體(B)自行生一
個資源ID, 所以初始實體(A)送出一個空的bind元素
</iq>
(B) . 初始實體(A)自行指定資源ID, 則初始實體(A)可發送包含期望資源ID的 “set” 類型IQ節(<iq/>) Client à Server <iq type='set' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource> è 初始實體(A)自行指定期望綁定資源
</bind>
</iq>
接收實體(B)可接受初始實體(A)所提供的資源ID, 但接收實體(B)也可生成其資源ID去覆蓋它, 而在這種情況下, 接收實體(B)不可返回一個錯誤訊息給初始實體(A), 而需把其生成資源ID透過IQ節 “result” 類型返回給客戶端
當初始實體(A)自行提供綁定資源ID時, 可能會發生以下錯誤情況
1. 初始實體(A)所提供的資源ID, 接收實體(B)無法處理(例如:不符合資源字符規範) Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
2. 初始實體(A)是不被允許綁定一個資源 Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
3. 初始實體(A)所提供的資源ID已被使用(初始實體(A)不允許同一個資源ID綁定多個連結) Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
9. XML節(STANZAS)
在通過TLS,SASL,BIND之後, 就可發送XML節, 在 ‘jabber:client’ 和 ‘jabber:server’命名空間中定義了3種xml節(<message/>,<presence/>,<iq/>)而這3種xml節包含了5種型態通用屬性(to、from、id、type、xml:lang)
9.2.1 信(訊)息節(<message/>)
<message/>節類型可以被視為一個”push”機制, 運用於一個發送實體發送信息給一個接收實體(例如: email中的送信), <message/>節需明定一個信息接收者屬性(to), 一個<message/>節中的 “type” 屬性是被建議的, 如果包含了 “type” 屬性它指明這個信息的會話上下文, 其 “type” 屬性必需是以下值之一 (chat, error, groupchat, headline, normal), 其type屬性說明了這個信息的類型, 一個接收端接收了一個沒有type屬性的信息, 則需將該message視為normal(normal為預設值), 一個<message/>節可以包含任何適當的命名空間的子元素, 但若<message/>節是屬於type=error類型的其子元素必需包含一個<error/>子元素, <message/>節可以包含以下子元素任何一種並且無需聲明命名空間
屬性
to
指明該信息要發送給哪一個接收實體
必要的
from
id
type
指明該信息的訊息類型(chat, error, groupchat, headline, normal)
1. 傳遞內容未包含以noraml代替
2. type=error需包含<error/>子元素
可省略
xml:lang
1. <subject/>子元素(該元素不需聲明命名空間)
Subject(信(訊)息主題)子元素包含了人可讀取的xml字符資料, 其用於指明這個信息的主題, 該子元素不可有任何屬性(但xml:lang除外), subject子元素可運用xml:lang屬性將信息主題以各種不同語言版本呈現, 但每個subject子元素xml:lang屬性值需互不相同才可以
2. <body/>子元素(該元素不需聲明命名空間)
Body(信息內容)子元素同樣也屬於人可讀取的xml字符資料, 其子元素用於表達該信(訊)息的內容, 該子元素不可有任何屬性(但xml:lang除外), body子元素可運用xml:lang屬性將信息內容以各種不同語言版本呈現, 但每個body子元素xml:lang屬性值需互不相同才可以
3. <thread>
Thread(信(訊)息追踪線索)子元素為人無法判讀的xml字符資料, 用於追踪2個實體間的會話線索
子元素
xml字符資料
屬性
資料內容
說明
subject
可被人判讀
不可有屬性(xml:lang除外)
於<message/>節可有1~N個
必需
body
可被人判讀
不可有屬性(xml:lang除外)
於<message/>節可有1~N個
必需
thread
不可被判讀
不可有屬性
必需
9.2.2 出席信(訊)息節(<presence/>)
<presence/>節可以被視為一個廣播或出版訂閱機制, 用於多個實體接收某個已訂閱實體的信息, 通常一個發送實體不應該包含 “to” 屬性來發送一個出席信息節, 而該發送實體所連接的服務器應該廣播給那些有訂閱該發送實體當前的網路可用性(例如: 離線, 線上, 離開…..等等)的其它發送實體, <presence/>節的 “type”屬性是可被選擇性使用的(未包含type屬性的出席信(訊)息節<presence/>表示發送端已在線上並可進行通信), 其<presence/>節 “type”屬性值可包含如(unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error), 一個<presence/>節可以包含任何適當命名空間的子元素, 如果<presence/>節的type=error, 必需包含一個<error/>子元素, 一個<presence/>節若沒有包含 “type” 屬性的話, 它可以包含以下任何子元素
屬性
to
不必要
from
id
type
指明該信息的訊息類型(unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error)
1. 傳遞內容未包含視為已在線上並可進行通信, 及可包含子元素
2. type=error需包含<error/>子元素
可省略
xml:lang
1. <show/>
該子元素是選擇性的, 該子元素所包含的xml資料不可供人所閱讀, 該子元素所要表達的是一個實體或資源的可用性狀態, 一個<presence/>節只可包含一個<show/>子元素, 而該子元素不可擁有任何屬性, 其子元素的xml資料內容可使用以下說明中之一項(away、chat、dnd、xa), 若<presence/>節沒有包含<show/>子元素則該實體的狀態被視為 “在線上” 或 “可使用”
2. <status/>
該子元素是選擇性的, 其元素的xml資料乃用來表達<show/>子元素可用性更詳細的描述說明(例如: 會議中), 而<status/>子元素也不可擁有任何屬性, 但除了xml:lang除外
3. <priority/>
該子元素是選擇性的, 該子元素的xml資料不可被人所閱讀, 其用來指明資源的優先權級別, 該值需介於-128 ~ 127之間, 一個<presence/>節只可有一個<priority/>子元素, 而該子元素也不可擁有任何屬性, 若該子元素未被提供則其優先權級別視為0
子元素
xml字符資料
屬性
資料內容
說明
show
不可被判讀
不可有屬性
away、chat、dnd、xa
於<presence/>節只可有1個
選擇性
未提供以在線上或可使用替代
status
可被人判讀
不可有屬性(xml:lang除外)
於<presence/>節可有1~N個
選擇性
priority
不可被判讀
不可有屬性
於<presence/>節只可有1個
選擇性
未提供以0替代
9.2.3 IQ節(<iq/>)
<iq/>節是一個信息請求/查詢回應(Inof/Query)的一個機制, 類似http, <iq/>節使一個實體(A)向另一個實體(B)做出請求, (B)實體回應(A)實體結果, 請求和應答的資料是被定義在一個直的子元素命名空間聲名中, 並且由請求實體用 “id”屬性來做為跟踪彼此交互行為, IQ交互乃伴隨著一個結構化的資料交換通用模式, 例如: get/result(error) 或 set/result(error)
執行iq節, 需應用以下規則
1. <iq/>節中的 “id” 屬性是必需的
2. <iq/>節中的 “type” 屬性是必需的, 其屬性只可為以下內容之一項
甲、get – 表示這個<iq/>節是一個對信息或需求的請求
乙、set – 表示這個<iq/>節提供資料, 用於設置新的值, 或取代現有的值
丙、result – 表示對這個<iq/>節的請求(get)或提供資料(set), 所給予的應答
丁、error – 應答發生錯誤, 表示對這個<iq/>節的請求(get)或提供資料(set), 所給予的錯誤應答
3. 一個實體接收到 “get” 或 “set” 類型的<iq/>節, 該實體必需回應一個 “result “ 或 “error” 類型的<iq/>節, 以做為回應, 其回應的<iq/>節其 “id”屬性需與請求(get)或提供資料(set)的<iq/>節一致
4. 一個實體接收到 “result” 或 “error” 類型的<iq/>節, 不可發發送同樣的“result” 或 “error” 類型的<iq/>節做為應答
5. 一個 “get” or “set”類型的<iq/>節必需包含一個子元素以做為指明請求或提供資料的資料來源
6. 一個 “result” 類型的<iq/>節必需包含零或一個子元素做為指明回應的資料來源
7. 一個 “error” 類型的<iq/>節必需包含當初 “get” or “set”類型<iq/>節所傳送的子元素及一個<error/>子元素以做為回應
9.3 xml節的錯誤
節錯誤的處理方式類似xml流的錯誤, 但節(stanzas)錯誤是可被恢復的, 所以節錯誤也包含了用來暗示原來發送者可用什麼方式來補求節錯誤的方法
節(stanzas)錯誤的規則
1. 接收或處理實體接收到一個節錯誤時應該返回相同類型的節給發送實體(需回應相同類型節的type屬性值需要設置為 “error”
2. 接收或處理實體返回相同類型節給發送實體時, 需包含原發送的xml資料內容, 這樣可以讓發送實體去檢查錯誤的原因
3. 返回一個相同類型的節需包含<error/>子元素
4. 如果返回一個相同類型的節type屬性不為 “error” 則不可包含<error/>子元素
<stanza-kind to='sender' type='error'>
[RECOMMENDED to include sender XML here]
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'>
OPTIONAL descriptive text
</text>
[OPTIONAL application-specific condition element]
</error>
</stanza-kind>
stanza – kind如<message/>, <presence/>, <iq/>節
error – type可包含如下值之一 (cancel, continue, modify, auth, wait)
defined-condition – <bad-request/>, <conflict/>, <feature-not-implemented/>,……
<unexpected-request/>等(可參考RFC-3920中的9.3.3已定義的條件)
2. 清算運用之前研討會分享作法實作
1.如何將perl 模組安裝到私有的目錄(luke於2006/11/15分享)
目前電腦教室及清算系統都將系統會使用到的模組的source code及install分別安裝至特定目錄位置, 讓se在安裝系統時可以把系統整個tar過去及解tar後就可執行installer的安裝過程
原始分享內容截錄
A.解開perl 模組(http://www.cpan.org/)
tar zxvf mmm.tgz
perl Makefile.PL PREFIX=/usr/local/Portal/perlmods LIB=/usr/local/Portal/perlmods
make
make install
B.程式裡的模組叫用方式
一. unshift(@INC,'/usr/local/Portal/perlmods');
二. use lib '/usr/local/Portal/perlmods' ;
2.如何替perl開發的軟體撰寫installer (luke於2006/11/15分享)
電腦教室及清算系統installer的內容大都是對系統會使用到的設定檔(conf file)及建置資料庫及匯入資料至資料……等一些預設性的工作所做的編寫, se在執行完installer後即可使用該系統, 不用再花費更多人力去建置一個系統所需預設的工作
3.upgrade 系統設定及運作原理 (luke於2006/11/15分享)
卡務,電腦教室及清算系統目前皆是採用luke提供的upgrade system做為程式bug修正及版本更新的傳遞upgrade管道, 只需把已修正過程式更新至server端的upgrade目錄下,即可透過upgrade程式將server端已修正的程式自動更新至client端
原始分享內容截錄
#要做簽章的起始目錄
computer_initdir: /usr/local/computer_pkg20060704_v1
computer_exclude: [dir]storage
computer_exclude: [dir]sync
computer_exclude: [dir]upgrade
computer_exclude: [dir]WOL
computer_exclude: [dir]conf
computer_exclude: [dir]temp
computer_exclude: [dir]test
computer_exclude: [dir]backup
computer_exclude: [dir]tmp
#額外需要做簽章的檔案(需要填實際的位置)
#iniDB目錄下的檔案不做upgrade處理, 另開發3支mysql檔案需做額外簽章
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/altertbl.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/dropdb.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/addsshtbl.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/html/conf/action.conf
#執行指令
computer_cmds: /bin/chmod -R 750 /usr/local/computer/image;/bin/chown -R computer:computer /usr/local/computer/image
computer_cmds: /bin/chmod 750 /usr/local/computer/iniDB/altertbl.mysql;/bin/chmod 750 /usr/local/computer/iniDB/dropdb.mysql;/bin/chmod 750 /usr/local/computer/iniDB/addsshtbl.mysql
computer_cmds: /bin/chmod 750 /usr/local/computer/tools/addtbl.pl;
………………………………………………………………
………………………………………………………………
………………………………………………………………
#要做簽章的起始目錄
computerv2_initdir: /usr/local/computer_pkg20070302_v2
#[file] 檔案包含xx 不做簽章 [dir]目錄名稱包含yy 不做簽章
computerv2_exclude: [file].md5
computerv2_exclude: [file].bak
computerv2_exclude: [file].gz
computerv2_exclude: [file].cf
computerv2_exclude: [file].db
………………………………………………………………
………………………………………………………………
………………………………………………………………
4.Data::Dumper 的使用 (luke於2007/01/18分享)
在之前的卡務及電腦教室對於設定檔的資料, 皆是以share memory方式做為程式讀設定檔的方式, 而清算系統則是改採Data::Dumper做為設定檔讀取方式, 只要將設定檔格式先行轉換成hash(雜湊函數)方式存放於另一個檔案中, 即可以perl中以hash方式叫用設定檔內容
原始分享內容截錄
四.Data::Dumper 的使用
A.Data::Dumper 並非perl內建模組,請自行使用cpan 安裝,或是下載src回來後自行安裝
B.Data::Dumper 主要的用途是把資料結構轉換成檔案結構,反之亦然
C.
#exam3.pl
#!/usr/bin/perl
use Data::Dumper;
my %conf;
open(my $HANDLE,"system.cf");
while(<$HANDLE>){
$_=~tr/\r\n//d;
if ($_ eq ''){next;}
my ($p,$v)=split(': ',$_);
$conf{uc($p)}=$v;
}
close($HANDLE);
open(my $HANDLE2,">system.cache");
$Data::Dumper::Terse = 1;
print $HANDLE2 Dumper(\%conf);
close($HANDLE2);
#exam4.pl
#!/usr/bin/perl
use Data::Dumper;
my $conf;
my $code='';
{
local $/=undef;
open(my $HANDLE2,"system.cache");
my $cache=<$HANDLE2>;
close($HANDLE2);
$code='$conf=' . $cache;
}
print "=======my code========\n";
print $code;
print "=======================\n";
eval "$code";
foreach my $k(keys %{$conf}){
print "$k=>" . $conf->{$k}. "\n";
}
5.樣板的使用 (luke於2007/01/18分享)
在卡務及電腦教室並沒有所謂樣板的觀念在使用, 往往對於html皆是撰寫於程式中, 所以一旦畫面格式要更動修改, 皆需由rd自行修正, 容易造成rd要花多餘的時間來做這件事, 所以於清算系統則採用樣板模式, rd只需產生樣板所需的資料後套用至樣板中即可使用, 而清算所使用的方式乃是用xml及xsl做配搭, 由製作頁面的人員施作xsl, 由rd產生xml去配搭所對應的xsl再轉換成html即可將畫面顯示在web上, 一旦畫面格式有異動只需請頁面製作人員修正頁面, 若是異動(新增或刪除)部份資料, 則由rd去修正相對應的xml再告知頁面製作人員修正即可, 這樣比較有所謂的分工的觀念在裡面
目前清算系統部份取代方式乃是使用的是取代變數中的方法一
原始分享內容截錄
b.取代變數的做法
方法論一.
Step 1. 首先,我們把程式與網頁分開
參考範例:實際上的目錄規劃我們在上次的研討會提過,應該是
/usr/local/Product_Name/Function_Type
程式/網頁/設定檔
虛擬目錄
實體目錄
exam6.pl
/octopus/html/test/cgi-bin
/usr/local/octopus/html/test/cgi-bin
myhtml.htm
/usr/local/octopus/html/test/templet
system.cf
/usr/local/octopus/html/test/conf
Step 2. 使用架構去讀取外部網頁
Step 3. 使用perl 的強項regular expression 把變數做替換
#exam6.pl
#http://tcmail.program.com.tw/octopus/test/cgi-bin/exam6.pl?src=myhtml.htm
#!/usr/bin/perl
use strict;
my $buffer = $ENV{QUERY_STRING};
my %IN;
my @nv_pairs = split( /\&/, $buffer );
foreach my $nvp ( 0 .. $#nv_pairs )
{
$nv_pairs[$nvp] =~ tr/+/ /;
my ( $key, $keyword ) = split( /=/, $nv_pairs[$nvp], 2 );
$key =~ s#%(..)#pack("c",hex($1))#ge;
$key =~ tr/[A-Z]/[a-z]/;
$keyword =~ s/%(?:([0-9a-fA-F]{2})u([0-9a-fA-F]{4}))/defined($1)? chr hex($1) : chr hex($2)/ge;
$IN{$key} .= "\0" if ( defined( $IN{$key} ) );
$keyword =~ s/\`\ \"\'\>\<//gs;
$IN{$key} .= $keyword;
}
my %varhash;
$varhash{UID}='luke';
$varhash{PASSWD}='lukePASSWD';
my $htmlstr='';
{
local $/=undef;
open (my $HANDLE,"/usr/local/octopus/html/test/templet/" . $IN{src});
$htmlstr=<$HANDLE>;
close($HANDLE);
}
$htmlstr =~ s/\$([A-Z]+)/
my $value = $varhash{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;
print "Content-Type: text/html; charset=big5\r\n\r\n";
print $htmlstr ;
#myhtml.htm
<html>
<body>
這樣好多了,不是嗎? 我的變數不會跟程式碼混在一起,<br>
而且當網頁要修改時,我們不需要大費周章把程式碼翻<br>
出來,而且你看, 我這邊以一樣可以使用取代的方式讓靜<br>
態的網頁呈現動態的資訊<br><br>
比如:變數 UID 我可以置換成$UID <br>
比如:變數 PASSWD 我可以置換成$PASSWD <br>
請注意我沒有這個變數 $NOVAR 的值<br><br>
真好,不是嗎,但當我有邏輯要在網頁運行時怎麼辦??<br>
</body>
</html>
方法論二.
將程式與設定分離,使用動態的CACHE/CONFIG 來呈現樣式
#exam7.pl
#http://tcmail.program.com.tw/octopus/test/cgi-bin/exam7.pl?src=myhtml.htm
#!/usr/bin/perl
use strict;
my $buffer = $ENV{QUERY_STRING};
my %IN;
my @nv_pairs = split( /\&/, $buffer );
foreach my $nvp ( 0 .. $#nv_pairs )
{
$nv_pairs[$nvp] =~ tr/+/ /;
my ( $key, $keyword ) = split( /=/, $nv_pairs[$nvp], 2 );
$key =~ s#%(..)#pack("c",hex($1))#ge;
$key =~ tr/[A-Z]/[a-z]/;
$keyword =~ s/%(?:([0-9a-fA-F]{2})u([0-9a-fA-F]{4}))/defined($1)? chr hex($1) : chr hex($2)/ge;
$IN{$key} .= "\0" if ( defined( $IN{$key} ) );
$keyword =~ s/\`\ \"\'\>\<//gs;
$IN{$key} .= $keyword;
}
my %varhash;
$varhash{UID}='luke';
$varhash{PASSWD}='lukePASSWD';
$varhash{EXISTS}='已經有';
my $htmlstr='';
{
local $/=undef;
open (my $HANDLE,"/usr/local/octopus/html/test/templet/" . $IN{src});
$htmlstr=<$HANDLE>;
close($HANDLE);
}
$htmlstr =~ s/\$([A-Z]+)/
my $value = $varhash{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;
my %conf;
open(my $HANDLE,"/usr/local/octopus/html/test/conf/system.cf");
while(<$HANDLE>){
$_=~tr/\r\n//d;
i f ($_ eq ''){next;}
my ($p,$v)=split(': ',$_);
print "$p\t$v";
$conf{uc($p)}=$v;
}
close($HANDLE);
$htmlstr =~ s/\$([A-Z]+)/
my $value = $conf{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;
print "Content-Type: text/html; charset=big5\r\n\r\n";
print $htmlstr ;
清算xml樣板套用方式 (standard.xml)
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="http://se6.program.com.tw/liquxsl/$APNAME0"?>
<liquidate>
<info>
<apname>$APNAME</apname>
<title>$TITLE</title>
<splitchk>$SPLITCHK</splitchk>
<nowpage>$NOWPAGE</nowpage>
<totalpage>$TOTALPAGE</totalpage>
<rows>$ROWS</rows>
<host>$HOST</host>
<action>$ACTION</action>
<src>$SRC</src>
<backaction>$BACKACTION</backaction>
<backsrc>$BACKSRC</backsrc>
</info>
<data>
$XMLRECORDSET
</data>
</liquidate>
6.清算對於json的運用
清算對於json的運用乃運用在角色及權限上, 將各個角色轉換成json模式存放, 再將該json檔案付予使用這個角色的權限, 並透過讀取json檔案的程式將內容讀取出來, 已做為程式在top及left的functions的顯示
清算json存放模式
Top function json檔案內容
var func0 = [
{
funcacid: '1',
funcadesc: '系統管理'
},
{
funcacid: '2',
funcadesc: '資料管理'
},
{
funcacid: '4',
funcadesc: '清算管理'
},
{
funcacid: '8',
funcadesc: '報表管理'
},
{
funcacid: '16',
funcadesc: '核銷帳務管理'
},
{
funcacid: '32',
funcadesc: '資料查詢管理'
},
];
Left function json檔案內容
var func1 = [
{
rank: '41',
funcdesc: '管理角色定義',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=roleslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
{
rank: '42',
funcdesc: '管理權限設定',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=managerslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
{
rank: '43',
funcdesc: 'IP存取設定',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=blackipslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
];
讀取json的html檔案
Top Functions html原始檔案
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上頁框主功能頁</title>
<link href="../../liqu_image/css/top.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$URL"></script>
<script type="text/javascript" src="../../liqu_image/js/frameName.js"></script>
<script type="text/javascript" src="../../liqu_image/js/topjsondata.js"></script>
<script type="text/javascript">
<!--
function initPage(){
createFun($VARIABLE);
}
window.onload = initPage;
//-->
</script>
</head>
<body>
<div class="bg01" align="center">
<div class="bgarea">
<div id="funArea" class="funArea"> </div>
</div>
</div>
<div class="locName">您現在位置:<span id="itemName"> </span></div>
</body>
</html>
Top Functions html web顯示內容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上頁框主功能頁</title>
<link href="../../liqu_image/css/top.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://se6.program.com.tw/liquidate/getjsondata.pl?type=eA9t"></script>
<script type="text/javascript" src="../../liqu_image/js/frameName.js"></script>
<script type="text/javascript" src="../../liqu_image/js/topjsondata.js"></script>
<script type="text/javascript">
<!--
function initPage(){
createFun(func0);
}
window.onload = initPage;
//-->
</script>
</head>
<body>
<div class="bg01" align="center">
<div class="bgarea">
<div id="funArea" class="funArea"> </div>
</div>
</div>
<div class="locName">您現在位置:<span id="itemName"> </span></div>
</body>
</html>
3.5 地址的確認
在SASL(見第六章)握手之後(如果必要的話,也在資料綁定(見第七章)之後,正在接收信息的實體必須(MUST)確認初始實體的ID
對於服務器間的通信,在SASL握手時,如果沒有指明授權的ID,這個初始的實體應該(SHOULD)是經過認證實體(參見簡單認證和安全層協議[SASL]中的定義)授權的ID(見第六章)
對於客戶端和服務器的通信, 在SASL握手時, 如果沒有指明授權的ID, “純JID” (<node@domain>)應該(SHOULD)是經過認證實體(參見[SASL]中的定義)授權的ID, “全JID”(<node@domain/resource>)的資源ID部份應該(SHOULD)是由客戶端和服務器在資源綁定的時候商定的(參見第七章)
4.1 XML流 / XML節概覽
XML流(XML Stream)的定義: 一個XML流乃是一個容器, 包含了2個實體之間通過網絡交換XML元素, 一個XML流乃由一個<stream>標籤開始的(該標籤需包含適當的屬性及名字空間聲明), XML流的結束則是由</stream>標籤做為結束, 在XML流的整個生命週期中, 初始化它的實體可以通過流來發送大量的XML元素, 例如:TLS協議(第5章),SASL協議(第6章)或XML節(在這裡指的是符合預設名字空間的元素, 包括<message/>,<presence/>,<iq/>元素), “初始的XML流"由初始實體(通常是一個客戶端或服務器)和接收實體(通常為一個服務器)協議, 從接收實體來看, XML流就是那個初始實體對接收實體的 “會話”, 接收實體則必需回覆一個相同的應答流給初始實體
Ex:
<stream> è xml流開始
……………………………….
……………………………….
</stream> è xml流結束
XML節(XML Stanzas)的定義 : 一個XML節是一個實體通過XML流向另一個實體發送結構化信息中的一個離散語意單位, 一個XML節乃直接存於根元素<stream/>之下, 也就是說任何XML都是從一個XML流的下一級的某個OPEN標籤(如: <presence>)開始的, 並相對應到其CLOSE標籤(如: </presence>)做為結束, 一個XML節可以包含子元素(例如: 屬性, 元素, XML字符…..等資料)以表達整個完整的信息, 然而在定義的XML只限定於<message/>,</presence>,</iq>這3個元素, 其TLS / SASL / 服務器回撥所需發送的XML元素, 則不被視為一個XML節
Ex:
<stream> è xml流開始
………. è TLS協議 (可省略)
………. è SASL協議
<presence> è xml節開始
<show/> è xml節子元素
</presence> è xml節結束
<message> è xml節開始
<body/> è xml節子元素
</message> è xml節結束
……………………………….
……………………………….
</stream> è xml流結束
XML流與XML節圖示
---------------------------- <stream> ---------------------------- <presence> <show/> </presence> ---------------------------- <message to='foo'> <body/> </message> ---------------------------- <iq to='bar'> <query/> </iq> ---------------------------- … ---------------------------- </stream> ----------------------------
4.3 流的安全
在XMPP 1.0中, 對於流的安全性可使用TLS及SASL已做為初始實體(發送初始化流 Send Default XML Stream)與接收實體(發送應答流 Response XML Stream)已做為安全傳送機制, 若XML流在被真實驗證之前, 實體不該發送任何XML節(XML Stanza), 即使當一方於流被驗證之前發送了XML節, 另一方實體則不能接受這些節的傳入, 應該返回一個<not-authorized/>的錯誤訊息及終止當前雙方TCP連結的XML流
4.4 XML流(XML Stream)的屬性
屬性 初始實體(A) à 接收實體(B) 接收實體(B) à 初始實體(A)
to 接收實體(B)的主機名稱 可忽略
from 可省略 接收實體(B)的主機名稱
id 可省略 協議key值
xml:lang 預設語言 預設語言
version xmpp 1.0 xmpp 1.0
初始實體(A)可以為客戶端或伺服器端(Client à Server Or Server à Server) 初始實體(A) è 接收實體(B) <stream:stream
xmlns='jabber:client' Or xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>接收實體(B) è 初始實體(A) <stream:stream
xmlns='jabber:client' Or xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123' à 協議key值
from='B.Server.com'
version='1.0'>
5.1 TLS的使用概覽
XMPP包含了一個可讓XML流被防止篡改及偷聽的安全方法, 類似SSL的觀念
TLS使用原則需在SASL使用之前被使用, TLS可以在2個網域之間確保通信之間的安全, 其TLS使用方式步驟如下(初始實體[可以為客戶端(Client)或伺服器端(Server)]稱呼為 A, 接收實體[伺服器端(Server)]稱呼為 B)
1 . A透過TCP連接, 發送一OPEN之XML流信息(需包含版本這個屬性)給B【Client à Server】 <stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>
2. B也透過TCP連接, 發送一個XML流信息(需包含版本這個屬性)給A【Server à Client】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123' Or id='s2s_123'
from='B.Server.com'
version='1.0'>
3. B向A提議STARTTLS的範圍(包含version屬性), 包含驗證機制及其它流特性【Server à Client】<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'> è TLS協議
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> è SASL協議
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
4. A發出STARTTLS協議以通知B, 希望開始啟用 TLS保護XML流(XML Stream)
【Client à Server】<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
5. B發出<proceed/>或<failure/>元素做為回應, 回應<failure/>元素者終止XML流及TCP連接
【Server à Client】<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
OR <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream:stream>
6. TLS協議成功, 則A需重新發送一個新OPEN的XML流信息給B(不需先行發送一個</stream>, 因為A與B必需確保原來的流在TLS協議成功後才被關閉)
【Client à Server】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:Server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>
7. B由A接收到一個新的XML流, 也需重新發送一個新的XML流給A以做為應答, 其重新應答可包含可用特性但不可包含STARTTLS特性【Server à Client】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:Server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='c2s_234' Or id='s2s_234'
version='1.0'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
6.1 SASL概覽
XMPP提供一個可以驗證XML流(XML Stream)的方法, SASL(簡單驗證安全層), 需
注意的是SASL協議時, 在XML元素中所使用的任何資料皆需被編碼成BASE64(參考RFC3548第3章), 若在使用SASL驗證機制之前明訂需使用TLS,則接收實體不可在TLS協議之前提供可用的SASL驗證清單
7. 資源綁定
初始實體(A)在與和接收實體(B)完成SASL協議之後, 若初始實體(A)想要或需要綁定一個特定的資源到XML流上, 就需採用資源綁定協議, 而資源綁定協議只適用於 [客戶端] (初始實體(A)可以為客戶端或為伺服器), 客戶端必需擁有一個相關資源ID(可由接收實體(B)或初始實體(A)程序提供), 而在XML流上的地址是一個 [全JID] (<node@domain/resource>), 在SASL協議成功後接收實體(B)需回應一個新XML流(XML Stream), 接收實體(B)若需初始實體(A)綁定一個資源, 必需在新的XML流中包含一個空的<bind/>元素 接收實體(B) è 初始實體(A), B要求A需做binding resource機制 <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_345' from='B.Server.com' version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
初始實體(A)收到接收實體(B)發送的bind通知後, 初始實體(A)需發送一個 “set” 類型的IQ節(<iq/>)給接收實體(B)來綁定一個資源到xml流中
(A) . 初始實體(A)希望接收實體(B)生成一個資源ID, 則初始實體(A)可發送一個空的<bind/>元素的 “set” 類型IQ節(<iq/>) Client à Server <iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/> è 初始實體(A)希望由接收實體(B)自行生一
個資源ID, 所以初始實體(A)送出一個空的bind元素
</iq>
(B) . 初始實體(A)自行指定資源ID, 則初始實體(A)可發送包含期望資源ID的 “set” 類型IQ節(<iq/>) Client à Server <iq type='set' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource> è 初始實體(A)自行指定期望綁定資源
</bind>
</iq>
接收實體(B)可接受初始實體(A)所提供的資源ID, 但接收實體(B)也可生成其資源ID去覆蓋它, 而在這種情況下, 接收實體(B)不可返回一個錯誤訊息給初始實體(A), 而需把其生成資源ID透過IQ節 “result” 類型返回給客戶端
當初始實體(A)自行提供綁定資源ID時, 可能會發生以下錯誤情況
1. 初始實體(A)所提供的資源ID, 接收實體(B)無法處理(例如:不符合資源字符規範) Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
2. 初始實體(A)是不被允許綁定一個資源 Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
3. 初始實體(A)所提供的資源ID已被使用(初始實體(A)不允許同一個資源ID綁定多個連結) Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
9. XML節(STANZAS)
在通過TLS,SASL,BIND之後, 就可發送XML節, 在 ‘jabber:client’ 和 ‘jabber:server’命名空間中定義了3種xml節(<message/>,<presence/>,<iq/>)而這3種xml節包含了5種型態通用屬性(to、from、id、type、xml:lang)
9.2.1 信(訊)息節(<message/>)
<message/>節類型可以被視為一個”push”機制, 運用於一個發送實體發送信息給一個接收實體(例如: email中的送信), <message/>節需明定一個信息接收者屬性(to), 一個<message/>節中的 “type” 屬性是被建議的, 如果包含了 “type” 屬性它指明這個信息的會話上下文, 其 “type” 屬性必需是以下值之一 (chat, error, groupchat, headline, normal), 其type屬性說明了這個信息的類型, 一個接收端接收了一個沒有type屬性的信息, 則需將該message視為normal(normal為預設值), 一個<message/>節可以包含任何適當的命名空間的子元素, 但若<message/>節是屬於type=error類型的其子元素必需包含一個<error/>子元素, <message/>節可以包含以下子元素任何一種並且無需聲明命名空間
屬性
to
指明該信息要發送給哪一個接收實體
必要的
from
id
type
指明該信息的訊息類型(chat, error, groupchat, headline, normal)
1. 傳遞內容未包含以noraml代替
2. type=error需包含<error/>子元素
可省略
xml:lang
1. <subject/>子元素(該元素不需聲明命名空間)
Subject(信(訊)息主題)子元素包含了人可讀取的xml字符資料, 其用於指明這個信息的主題, 該子元素不可有任何屬性(但xml:lang除外), subject子元素可運用xml:lang屬性將信息主題以各種不同語言版本呈現, 但每個subject子元素xml:lang屬性值需互不相同才可以
2. <body/>子元素(該元素不需聲明命名空間)
Body(信息內容)子元素同樣也屬於人可讀取的xml字符資料, 其子元素用於表達該信(訊)息的內容, 該子元素不可有任何屬性(但xml:lang除外), body子元素可運用xml:lang屬性將信息內容以各種不同語言版本呈現, 但每個body子元素xml:lang屬性值需互不相同才可以
3. <thread>
Thread(信(訊)息追踪線索)子元素為人無法判讀的xml字符資料, 用於追踪2個實體間的會話線索
子元素
xml字符資料
屬性
資料內容
說明
subject
可被人判讀
不可有屬性(xml:lang除外)
於<message/>節可有1~N個
必需
body
可被人判讀
不可有屬性(xml:lang除外)
於<message/>節可有1~N個
必需
thread
不可被判讀
不可有屬性
必需
9.2.2 出席信(訊)息節(<presence/>)
<presence/>節可以被視為一個廣播或出版訂閱機制, 用於多個實體接收某個已訂閱實體的信息, 通常一個發送實體不應該包含 “to” 屬性來發送一個出席信息節, 而該發送實體所連接的服務器應該廣播給那些有訂閱該發送實體當前的網路可用性(例如: 離線, 線上, 離開…..等等)的其它發送實體, <presence/>節的 “type”屬性是可被選擇性使用的(未包含type屬性的出席信(訊)息節<presence/>表示發送端已在線上並可進行通信), 其<presence/>節 “type”屬性值可包含如(unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error), 一個<presence/>節可以包含任何適當命名空間的子元素, 如果<presence/>節的type=error, 必需包含一個<error/>子元素, 一個<presence/>節若沒有包含 “type” 屬性的話, 它可以包含以下任何子元素
屬性
to
不必要
from
id
type
指明該信息的訊息類型(unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error)
1. 傳遞內容未包含視為已在線上並可進行通信, 及可包含子元素
2. type=error需包含<error/>子元素
可省略
xml:lang
1. <show/>
該子元素是選擇性的, 該子元素所包含的xml資料不可供人所閱讀, 該子元素所要表達的是一個實體或資源的可用性狀態, 一個<presence/>節只可包含一個<show/>子元素, 而該子元素不可擁有任何屬性, 其子元素的xml資料內容可使用以下說明中之一項(away、chat、dnd、xa), 若<presence/>節沒有包含<show/>子元素則該實體的狀態被視為 “在線上” 或 “可使用”
2. <status/>
該子元素是選擇性的, 其元素的xml資料乃用來表達<show/>子元素可用性更詳細的描述說明(例如: 會議中), 而<status/>子元素也不可擁有任何屬性, 但除了xml:lang除外
3. <priority/>
該子元素是選擇性的, 該子元素的xml資料不可被人所閱讀, 其用來指明資源的優先權級別, 該值需介於-128 ~ 127之間, 一個<presence/>節只可有一個<priority/>子元素, 而該子元素也不可擁有任何屬性, 若該子元素未被提供則其優先權級別視為0
子元素
xml字符資料
屬性
資料內容
說明
show
不可被判讀
不可有屬性
away、chat、dnd、xa
於<presence/>節只可有1個
選擇性
未提供以在線上或可使用替代
status
可被人判讀
不可有屬性(xml:lang除外)
於<presence/>節可有1~N個
選擇性
priority
不可被判讀
不可有屬性
於<presence/>節只可有1個
選擇性
未提供以0替代
9.2.3 IQ節(<iq/>)
<iq/>節是一個信息請求/查詢回應(Inof/Query)的一個機制, 類似http, <iq/>節使一個實體(A)向另一個實體(B)做出請求, (B)實體回應(A)實體結果, 請求和應答的資料是被定義在一個直的子元素命名空間聲名中, 並且由請求實體用 “id”屬性來做為跟踪彼此交互行為, IQ交互乃伴隨著一個結構化的資料交換通用模式, 例如: get/result(error) 或 set/result(error)
執行iq節, 需應用以下規則
1. <iq/>節中的 “id” 屬性是必需的
2. <iq/>節中的 “type” 屬性是必需的, 其屬性只可為以下內容之一項
甲、get – 表示這個<iq/>節是一個對信息或需求的請求
乙、set – 表示這個<iq/>節提供資料, 用於設置新的值, 或取代現有的值
丙、result – 表示對這個<iq/>節的請求(get)或提供資料(set), 所給予的應答
丁、error – 應答發生錯誤, 表示對這個<iq/>節的請求(get)或提供資料(set), 所給予的錯誤應答
3. 一個實體接收到 “get” 或 “set” 類型的<iq/>節, 該實體必需回應一個 “result “ 或 “error” 類型的<iq/>節, 以做為回應, 其回應的<iq/>節其 “id”屬性需與請求(get)或提供資料(set)的<iq/>節一致
4. 一個實體接收到 “result” 或 “error” 類型的<iq/>節, 不可發發送同樣的“result” 或 “error” 類型的<iq/>節做為應答
5. 一個 “get” or “set”類型的<iq/>節必需包含一個子元素以做為指明請求或提供資料的資料來源
6. 一個 “result” 類型的<iq/>節必需包含零或一個子元素做為指明回應的資料來源
7. 一個 “error” 類型的<iq/>節必需包含當初 “get” or “set”類型<iq/>節所傳送的子元素及一個<error/>子元素以做為回應
9.3 xml節的錯誤
節錯誤的處理方式類似xml流的錯誤, 但節(stanzas)錯誤是可被恢復的, 所以節錯誤也包含了用來暗示原來發送者可用什麼方式來補求節錯誤的方法
節(stanzas)錯誤的規則
1. 接收或處理實體接收到一個節錯誤時應該返回相同類型的節給發送實體(需回應相同類型節的type屬性值需要設置為 “error”
2. 接收或處理實體返回相同類型節給發送實體時, 需包含原發送的xml資料內容, 這樣可以讓發送實體去檢查錯誤的原因
3. 返回一個相同類型的節需包含<error/>子元素
4. 如果返回一個相同類型的節type屬性不為 “error” 則不可包含<error/>子元素
<stanza-kind to='sender' type='error'>
[RECOMMENDED to include sender XML here]
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'>
OPTIONAL descriptive text
</text>
[OPTIONAL application-specific condition element]
</error>
</stanza-kind>
stanza – kind如<message/>, <presence/>, <iq/>節
error – type可包含如下值之一 (cancel, continue, modify, auth, wait)
defined-condition – <bad-request/>, <conflict/>, <feature-not-implemented/>,……
<unexpected-request/>等(可參考RFC-3920中的9.3.3已定義的條件)
2. 清算運用之前研討會分享作法實作
1.如何將perl 模組安裝到私有的目錄(luke於2006/11/15分享)
目前電腦教室及清算系統都將系統會使用到的模組的source code及install分別安裝至特定目錄位置, 讓se在安裝系統時可以把系統整個tar過去及解tar後就可執行installer的安裝過程
原始分享內容截錄
A.解開perl 模組(http://www.cpan.org/)
tar zxvf mmm.tgz
perl Makefile.PL PREFIX=/usr/local/Portal/perlmods LIB=/usr/local/Portal/perlmods
make
make install
B.程式裡的模組叫用方式
一. unshift(@INC,'/usr/local/Portal/perlmods');
二. use lib '/usr/local/Portal/perlmods' ;
2.如何替perl開發的軟體撰寫installer (luke於2006/11/15分享)
電腦教室及清算系統installer的內容大都是對系統會使用到的設定檔(conf file)及建置資料庫及匯入資料至資料……等一些預設性的工作所做的編寫, se在執行完installer後即可使用該系統, 不用再花費更多人力去建置一個系統所需預設的工作
3.upgrade 系統設定及運作原理 (luke於2006/11/15分享)
卡務,電腦教室及清算系統目前皆是採用luke提供的upgrade system做為程式bug修正及版本更新的傳遞upgrade管道, 只需把已修正過程式更新至server端的upgrade目錄下,即可透過upgrade程式將server端已修正的程式自動更新至client端
原始分享內容截錄
#要做簽章的起始目錄
computer_initdir: /usr/local/computer_pkg20060704_v1
computer_exclude: [dir]storage
computer_exclude: [dir]sync
computer_exclude: [dir]upgrade
computer_exclude: [dir]WOL
computer_exclude: [dir]conf
computer_exclude: [dir]temp
computer_exclude: [dir]test
computer_exclude: [dir]backup
computer_exclude: [dir]tmp
#額外需要做簽章的檔案(需要填實際的位置)
#iniDB目錄下的檔案不做upgrade處理, 另開發3支mysql檔案需做額外簽章
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/altertbl.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/dropdb.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/addsshtbl.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/html/conf/action.conf
#執行指令
computer_cmds: /bin/chmod -R 750 /usr/local/computer/image;/bin/chown -R computer:computer /usr/local/computer/image
computer_cmds: /bin/chmod 750 /usr/local/computer/iniDB/altertbl.mysql;/bin/chmod 750 /usr/local/computer/iniDB/dropdb.mysql;/bin/chmod 750 /usr/local/computer/iniDB/addsshtbl.mysql
computer_cmds: /bin/chmod 750 /usr/local/computer/tools/addtbl.pl;
………………………………………………………………
………………………………………………………………
………………………………………………………………
#要做簽章的起始目錄
computerv2_initdir: /usr/local/computer_pkg20070302_v2
#[file] 檔案包含xx 不做簽章 [dir]目錄名稱包含yy 不做簽章
computerv2_exclude: [file].md5
computerv2_exclude: [file].bak
computerv2_exclude: [file].gz
computerv2_exclude: [file].cf
computerv2_exclude: [file].db
………………………………………………………………
………………………………………………………………
………………………………………………………………
4.Data::Dumper 的使用 (luke於2007/01/18分享)
在之前的卡務及電腦教室對於設定檔的資料, 皆是以share memory方式做為程式讀設定檔的方式, 而清算系統則是改採Data::Dumper做為設定檔讀取方式, 只要將設定檔格式先行轉換成hash(雜湊函數)方式存放於另一個檔案中, 即可以perl中以hash方式叫用設定檔內容
原始分享內容截錄
四.Data::Dumper 的使用
A.Data::Dumper 並非perl內建模組,請自行使用cpan 安裝,或是下載src回來後自行安裝
B.Data::Dumper 主要的用途是把資料結構轉換成檔案結構,反之亦然
C.
#exam3.pl
#!/usr/bin/perl
use Data::Dumper;
my %conf;
open(my $HANDLE,"system.cf");
while(<$HANDLE>){
$_=~tr/\r\n//d;
if ($_ eq ''){next;}
my ($p,$v)=split(': ',$_);
$conf{uc($p)}=$v;
}
close($HANDLE);
open(my $HANDLE2,">system.cache");
$Data::Dumper::Terse = 1;
print $HANDLE2 Dumper(\%conf);
close($HANDLE2);
#exam4.pl
#!/usr/bin/perl
use Data::Dumper;
my $conf;
my $code='';
{
local $/=undef;
open(my $HANDLE2,"system.cache");
my $cache=<$HANDLE2>;
close($HANDLE2);
$code='$conf=' . $cache;
}
print "=======my code========\n";
print $code;
print "=======================\n";
eval "$code";
foreach my $k(keys %{$conf}){
print "$k=>" . $conf->{$k}. "\n";
}
5.樣板的使用 (luke於2007/01/18分享)
在卡務及電腦教室並沒有所謂樣板的觀念在使用, 往往對於html皆是撰寫於程式中, 所以一旦畫面格式要更動修改, 皆需由rd自行修正, 容易造成rd要花多餘的時間來做這件事, 所以於清算系統則採用樣板模式, rd只需產生樣板所需的資料後套用至樣板中即可使用, 而清算所使用的方式乃是用xml及xsl做配搭, 由製作頁面的人員施作xsl, 由rd產生xml去配搭所對應的xsl再轉換成html即可將畫面顯示在web上, 一旦畫面格式有異動只需請頁面製作人員修正頁面, 若是異動(新增或刪除)部份資料, 則由rd去修正相對應的xml再告知頁面製作人員修正即可, 這樣比較有所謂的分工的觀念在裡面
目前清算系統部份取代方式乃是使用的是取代變數中的方法一
原始分享內容截錄
b.取代變數的做法
方法論一.
Step 1. 首先,我們把程式與網頁分開
參考範例:實際上的目錄規劃我們在上次的研討會提過,應該是
/usr/local/Product_Name/Function_Type
程式/網頁/設定檔
虛擬目錄
實體目錄
exam6.pl
/octopus/html/test/cgi-bin
/usr/local/octopus/html/test/cgi-bin
myhtml.htm
/usr/local/octopus/html/test/templet
system.cf
/usr/local/octopus/html/test/conf
Step 2. 使用架構去讀取外部網頁
Step 3. 使用perl 的強項regular expression 把變數做替換
#exam6.pl
#http://tcmail.program.com.tw/octopus/test/cgi-bin/exam6.pl?src=myhtml.htm
#!/usr/bin/perl
use strict;
my $buffer = $ENV{QUERY_STRING};
my %IN;
my @nv_pairs = split( /\&/, $buffer );
foreach my $nvp ( 0 .. $#nv_pairs )
{
$nv_pairs[$nvp] =~ tr/+/ /;
my ( $key, $keyword ) = split( /=/, $nv_pairs[$nvp], 2 );
$key =~ s#%(..)#pack("c",hex($1))#ge;
$key =~ tr/[A-Z]/[a-z]/;
$keyword =~ s/%(?:([0-9a-fA-F]{2})u([0-9a-fA-F]{4}))/defined($1)? chr hex($1) : chr hex($2)/ge;
$IN{$key} .= "\0" if ( defined( $IN{$key} ) );
$keyword =~ s/\`\ \"\'\>\<//gs;
$IN{$key} .= $keyword;
}
my %varhash;
$varhash{UID}='luke';
$varhash{PASSWD}='lukePASSWD';
my $htmlstr='';
{
local $/=undef;
open (my $HANDLE,"/usr/local/octopus/html/test/templet/" . $IN{src});
$htmlstr=<$HANDLE>;
close($HANDLE);
}
$htmlstr =~ s/\$([A-Z]+)/
my $value = $varhash{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;
print "Content-Type: text/html; charset=big5\r\n\r\n";
print $htmlstr ;
#myhtml.htm
<html>
<body>
這樣好多了,不是嗎? 我的變數不會跟程式碼混在一起,<br>
而且當網頁要修改時,我們不需要大費周章把程式碼翻<br>
出來,而且你看, 我這邊以一樣可以使用取代的方式讓靜<br>
態的網頁呈現動態的資訊<br><br>
比如:變數 UID 我可以置換成$UID <br>
比如:變數 PASSWD 我可以置換成$PASSWD <br>
請注意我沒有這個變數 $NOVAR 的值<br><br>
真好,不是嗎,但當我有邏輯要在網頁運行時怎麼辦??<br>
</body>
</html>
方法論二.
將程式與設定分離,使用動態的CACHE/CONFIG 來呈現樣式
#exam7.pl
#http://tcmail.program.com.tw/octopus/test/cgi-bin/exam7.pl?src=myhtml.htm
#!/usr/bin/perl
use strict;
my $buffer = $ENV{QUERY_STRING};
my %IN;
my @nv_pairs = split( /\&/, $buffer );
foreach my $nvp ( 0 .. $#nv_pairs )
{
$nv_pairs[$nvp] =~ tr/+/ /;
my ( $key, $keyword ) = split( /=/, $nv_pairs[$nvp], 2 );
$key =~ s#%(..)#pack("c",hex($1))#ge;
$key =~ tr/[A-Z]/[a-z]/;
$keyword =~ s/%(?:([0-9a-fA-F]{2})u([0-9a-fA-F]{4}))/defined($1)? chr hex($1) : chr hex($2)/ge;
$IN{$key} .= "\0" if ( defined( $IN{$key} ) );
$keyword =~ s/\`\ \"\'\>\<//gs;
$IN{$key} .= $keyword;
}
my %varhash;
$varhash{UID}='luke';
$varhash{PASSWD}='lukePASSWD';
$varhash{EXISTS}='已經有';
my $htmlstr='';
{
local $/=undef;
open (my $HANDLE,"/usr/local/octopus/html/test/templet/" . $IN{src});
$htmlstr=<$HANDLE>;
close($HANDLE);
}
$htmlstr =~ s/\$([A-Z]+)/
my $value = $varhash{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;
my %conf;
open(my $HANDLE,"/usr/local/octopus/html/test/conf/system.cf");
while(<$HANDLE>){
$_=~tr/\r\n//d;
i f ($_ eq ''){next;}
my ($p,$v)=split(': ',$_);
print "$p\t$v";
$conf{uc($p)}=$v;
}
close($HANDLE);
$htmlstr =~ s/\$([A-Z]+)/
my $value = $conf{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;
print "Content-Type: text/html; charset=big5\r\n\r\n";
print $htmlstr ;
清算xml樣板套用方式 (standard.xml)
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="http://se6.program.com.tw/liquxsl/$APNAME0"?>
<liquidate>
<info>
<apname>$APNAME</apname>
<title>$TITLE</title>
<splitchk>$SPLITCHK</splitchk>
<nowpage>$NOWPAGE</nowpage>
<totalpage>$TOTALPAGE</totalpage>
<rows>$ROWS</rows>
<host>$HOST</host>
<action>$ACTION</action>
<src>$SRC</src>
<backaction>$BACKACTION</backaction>
<backsrc>$BACKSRC</backsrc>
</info>
<data>
$XMLRECORDSET
</data>
</liquidate>
6.清算對於json的運用
清算對於json的運用乃運用在角色及權限上, 將各個角色轉換成json模式存放, 再將該json檔案付予使用這個角色的權限, 並透過讀取json檔案的程式將內容讀取出來, 已做為程式在top及left的functions的顯示
清算json存放模式
Top function json檔案內容
var func0 = [
{
funcacid: '1',
funcadesc: '系統管理'
},
{
funcacid: '2',
funcadesc: '資料管理'
},
{
funcacid: '4',
funcadesc: '清算管理'
},
{
funcacid: '8',
funcadesc: '報表管理'
},
{
funcacid: '16',
funcadesc: '核銷帳務管理'
},
{
funcacid: '32',
funcadesc: '資料查詢管理'
},
];
Left function json檔案內容
var func1 = [
{
rank: '41',
funcdesc: '管理角色定義',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=roleslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
{
rank: '42',
funcdesc: '管理權限設定',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=managerslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
{
rank: '43',
funcdesc: 'IP存取設定',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=blackipslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
];
讀取json的html檔案
Top Functions html原始檔案
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上頁框主功能頁</title>
<link href="../../liqu_image/css/top.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$URL"></script>
<script type="text/javascript" src="../../liqu_image/js/frameName.js"></script>
<script type="text/javascript" src="../../liqu_image/js/topjsondata.js"></script>
<script type="text/javascript">
<!--
function initPage(){
createFun($VARIABLE);
}
window.onload = initPage;
//-->
</script>
</head>
<body>
<div class="bg01" align="center">
<div class="bgarea">
<div id="funArea" class="funArea"> </div>
</div>
</div>
<div class="locName">您現在位置:<span id="itemName"> </span></div>
</body>
</html>
Top Functions html web顯示內容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上頁框主功能頁</title>
<link href="../../liqu_image/css/top.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://se6.program.com.tw/liquidate/getjsondata.pl?type=eA9t"></script>
<script type="text/javascript" src="../../liqu_image/js/frameName.js"></script>
<script type="text/javascript" src="../../liqu_image/js/topjsondata.js"></script>
<script type="text/javascript">
<!--
function initPage(){
createFun(func0);
}
window.onload = initPage;
//-->
</script>
</head>
<body>
<div class="bg01" align="center">
<div class="bgarea">
<div id="funArea" class="funArea"> </div>
</div>
</div>
<div class="locName">您現在位置:<span id="itemName"> </span></div>
</body>
</html>
erlang 幾個可參考的網站
http://www.planeterlang.org/
http://www.blogjava.net/killme2008/category/20770.html
http://erlang-china.org/
http://www.blogjava.net/killme2008/category/20770.html
http://erlang-china.org/
Saturday, October 27, 2007
我們該有怎麼樣的效率?
微軟打敗 Google,得到入股 Facebook 的機會,這類消息在現在的網路上已不算新鮮事,事實上這個新聞躺在我的收信軟體OUTLOOK EXPRESS 好幾天了,直到今天才真的把他打開來看,我對這新聞本身並沒有太多的感覺,而下面這段話才是我最感興趣的地方
<<內容摘自Mr./Ms. Days - 網路, 資訊, 觀察, 生活>>
Facebook 的身價現在被推高到將近五千億新台幣.如果你沒什麼概念五千億台幣到底有多少,那麼你可能記得我們鴻海集團的郭董曾經出過一本書,叫做《五千億傳奇-郭台銘的鴻海帝國》,當時鴻海集團(2005 年) 的總市值就是跟現在 Facebook 差不多.是的,這一家只有 300 人,完全沒有實體的產品,不到三歲的網路公司,他的市值跟我們郭董手下的鴻海集團相當
那麼這裡比較吸引人不是這公司的市值有多少,而是究竟多少人創造了這麼可觀的市值,我反思--如果;微程式有300人;他的市值該是多少? 如果其他軟體公司有300人,那他的市值又會是多少? 老實說:我並不期待也不覺得網路上說的那些暴利多了不起,我只想知道;怎樣的效率才是我們可以預期的?
<<內容摘自Mr./Ms. Days - 網路, 資訊, 觀察, 生活>>
Facebook 的身價現在被推高到將近五千億新台幣.如果你沒什麼概念五千億台幣到底有多少,那麼你可能記得我們鴻海集團的郭董曾經出過一本書,叫做《五千億傳奇-郭台銘的鴻海帝國》,當時鴻海集團(2005 年) 的總市值就是跟現在 Facebook 差不多.是的,這一家只有 300 人,完全沒有實體的產品,不到三歲的網路公司,他的市值跟我們郭董手下的鴻海集團相當
那麼這裡比較吸引人不是這公司的市值有多少,而是究竟多少人創造了這麼可觀的市值,我反思--如果;微程式有300人;他的市值該是多少? 如果其他軟體公司有300人,那他的市值又會是多少? 老實說:我並不期待也不覺得網路上說的那些暴利多了不起,我只想知道;怎樣的效率才是我們可以預期的?
Monday, October 8, 2007
Quicksort in Erlang using two list comprehensions
qsort([]) -> [];
qsort([PivotT]) ->
qsort([X X <- T, X <>= Pivot]).
===以上資料是錯誤的======
qsort([]) -> [];
qsort([Pivot|T]) ->
qsort([X||X<-T,X =< Pivot]) ++
[Pivot] ++
qsort([X||X<-T,X > Pivot]).
qsort([PivotT]) ->
qsort([X X <- T, X <>= Pivot]).
===以上資料是錯誤的======
qsort([]) -> [];
qsort([Pivot|T]) ->
qsort([X||X<-T,X =< Pivot]) ++
[Pivot] ++
qsort([X||X<-T,X > Pivot]).
Thursday, September 27, 2007
又是一個盲從的案例
今天電視新聞裡播著某傳銷公司的激烈爭執,裡面有這麼一段對話,讀書怎麼會無用的? 這不是我說的,是大前研一說的...我們似乎還是非常習慣穿著名牌,描述著事不關己的事物,引經據典;卻不深究字義外的涵義,囫圇吞棗的消化大量沒有營養的口號,前幾天;甚至看到有人問一個蠢問題~~...那些趨勢大師 管理大師...之云...,如果沒有自己的思考觀點,不如;不要知悉這些所謂的名人語錄,盡信書不如無書,我想;他的重點不是無書對吧!
新聞裡另外一個有趣的對話是這樣說的: 你是誰ㄚ! 我台大的, 呵呵... 用自己的學歷來陳述讀書不重要的論點,呵呵...真是有趣的邏輯,對照他的同事所說的話,萬般皆下品惟有讀書高... 這句話不知道是矛還是盾
新聞裡另外一個有趣的對話是這樣說的: 你是誰ㄚ! 我台大的, 呵呵... 用自己的學歷來陳述讀書不重要的論點,呵呵...真是有趣的邏輯,對照他的同事所說的話,萬般皆下品惟有讀書高... 這句話不知道是矛還是盾
Monday, September 24, 2007
Quicksort in Erlang
-module(sort).
-export([sort/1]).
sort([]) -> [];
sort([PivotRest]) ->
{Smaller, Bigger} = split(Pivot, Rest),
lists:append(sort(Smaller), [Pivotsort(Bigger)]).
split(Pivot, L) ->
split(Pivot, L, [], []).
split(Pivot, [], Smaller, Bigger) ->
{Smaller, Bigger};
split(Pivot, [HdTl], Smaller, Bigger) when Hd <>
split(Pivot, Tl, [HdSmaller], Bigger);
split(Pivot, [HdTl], Smaller, Bigger) when Hd >= Pivot ->
split(Pivot, T, Smaller, [HdBigger]).
-export([sort/1]).
sort([]) -> [];
sort([PivotRest]) ->
{Smaller, Bigger} = split(Pivot, Rest),
lists:append(sort(Smaller), [Pivotsort(Bigger)]).
split(Pivot, L) ->
split(Pivot, L, [], []).
split(Pivot, [], Smaller, Bigger) ->
{Smaller, Bigger};
split(Pivot, [HdTl], Smaller, Bigger) when Hd <>
split(Pivot, Tl, [HdSmaller], Bigger);
split(Pivot, [HdTl], Smaller, Bigger) when Hd >= Pivot ->
split(Pivot, T, Smaller, [HdBigger]).
Thursday, September 20, 2007
我們需要的是思考而不是口號
很多人都在談M型社會的來臨,似乎大前言一帶來了這個口號的趨勢,有很多似是而非的觀念由此衍伸,新聞裡動不動就是M型社會這個詞,然而;我們需要的是思考並不是口號;難道百年前的日本,天皇與庶民的結構就不是M型社會? 這值得我們思考,我並沒有指出現在貧富差距的現象是否正在擴大的問題,我只是講出很多人盲目追求口號的事實;是不是M化反而不是重點,我們思考口號背後的邏輯或是只是盲目 急躁的替自己或別人貼上標籤?很多東西不能囫圇吞棗照單全收的, 趨勢大師說的是方向,除了羅盤,船還需要舵才能航向目標,管理要配合規模,當規模不夠大,細部的作為應重於方向,不是說方向不重要而是對這種規模的組織;管理不是第一要務,太多的方向與趨勢預測像是座在沒有舵的船上,有再多的方向預測再精準的羅盤也無法到達目的
我們需要的是思考不是口號,這好像有點偏離這個BLOG 的調性,但是請思考看看;.NET 與JAVA 這幾年的纏鬥,以及網路上只有.NET才是王道的言論...與前述觀點是否異曲同工? 我們需要的其實是理解技術背後的邏輯,單純的技術觀點與思考,而不是隨波逐流,我們可以反過來看郭台銘最近的言論,請問他一件事,如果鴻海的績效這麼好,那麼是否代表鴻海的員工為的是興趣而不是錢;那麼在這樣的前提下,鴻海的配股如果少一半,我們應該有理由相信,鴻海會更賺錢,因為這些員工是為了興趣而工作 不會為了錢而離開,如果這個答案是否定的,那麼代表鴻海的員工是為了錢而非興趣而工作,那麼;鴻海又為何高薪聘僱那些他們自認為不是最好的員工?這似乎自相矛盾到不行,這裡只點出部份學而不思的毛病 盲從 且不經思考地"引經據典" 以及這類速食未經消化的謬誤,切勿淪為英國詩人Robert Browning在童話故事[吹笛人]所描述的耗子只知盲從起舞,多思考一些口號或技術背後真實的觀點,這樣對整體才是有益
我們需要的是思考不是口號,這好像有點偏離這個BLOG 的調性,但是請思考看看;.NET 與JAVA 這幾年的纏鬥,以及網路上只有.NET才是王道的言論...與前述觀點是否異曲同工? 我們需要的其實是理解技術背後的邏輯,單純的技術觀點與思考,而不是隨波逐流,我們可以反過來看郭台銘最近的言論,請問他一件事,如果鴻海的績效這麼好,那麼是否代表鴻海的員工為的是興趣而不是錢;那麼在這樣的前提下,鴻海的配股如果少一半,我們應該有理由相信,鴻海會更賺錢,因為這些員工是為了興趣而工作 不會為了錢而離開,如果這個答案是否定的,那麼代表鴻海的員工是為了錢而非興趣而工作,那麼;鴻海又為何高薪聘僱那些他們自認為不是最好的員工?這似乎自相矛盾到不行,這裡只點出部份學而不思的毛病 盲從 且不經思考地"引經據典" 以及這類速食未經消化的謬誤,切勿淪為英國詩人Robert Browning在童話故事[吹笛人]所描述的耗子只知盲從起舞,多思考一些口號或技術背後真實的觀點,這樣對整體才是有益
Monday, September 17, 2007
Tuesday, September 11, 2007
Sunday, September 9, 2007
Metaweb Query Language 這個有趣
The Metaweb Query Language (MQL) is based on JSON and query-by-example. The MQL and API documentation can be found on the Freebase website in the developers' area. There is also an online Query Editor tool, with many examples of MQL, at http://www.freebase.com/view/queryeditor/
perl CPAN Module:http://search.cpan.org/~skud/Metaweb-0.05/
perl CPAN Module:http://search.cpan.org/~skud/Metaweb-0.05/
Friday, September 7, 2007
pure function
A pure function:
Has no side effects
Return value depends only on arguments
Example:
sub factorial {
my $n = shift;
$n == 0 ? 1 : $n * factorial($n-1);
}
cache 只對pure function 有意義;這可以思考,查詢一個檔案的修改時間的這種function,他並非一個pure function,所以;對非pure function做cache 是沒有意義的,這裡有一個例子:
Highly Recursive Functions
sub fib {
my ($n) = @_;
return $n if $n ==0 || $n == 1;
return fib($n-2) + fib($n-1);
}
This function is very very slow!
Caching Fixes Recursion
Solution: Caching
@fib = (0, 1);
sub fib {
my ($n) = @_;
return $fib[$n] if defined $fib[$n];
return $fib[$n] = fib($n-1) + fib($n-2);
}
fib(20) computes fib(18) and fib(19)
fib(19) goes to compute fib(18)
But it is already in $fib[18]
Function is now very fast,Almost as fast as a pure iterative version,
Unlike the iterative version, this version required no ingenuity
以上文章節錄自 http://perl.plover.com/yak/hw-dcpm/
Has no side effects
Return value depends only on arguments
Example:
sub factorial {
my $n = shift;
$n == 0 ? 1 : $n * factorial($n-1);
}
cache 只對pure function 有意義;這可以思考,查詢一個檔案的修改時間的這種function,他並非一個pure function,所以;對非pure function做cache 是沒有意義的,這裡有一個例子:
Highly Recursive Functions
sub fib {
my ($n) = @_;
return $n if $n ==0 || $n == 1;
return fib($n-2) + fib($n-1);
}
This function is very very slow!
Caching Fixes Recursion
Solution: Caching
@fib = (0, 1);
sub fib {
my ($n) = @_;
return $fib[$n] if defined $fib[$n];
return $fib[$n] = fib($n-1) + fib($n-2);
}
fib(20) computes fib(18) and fib(19)
fib(19) goes to compute fib(18)
But it is already in $fib[18]
Function is now very fast,Almost as fast as a pure iterative version,
Unlike the iterative version, this version required no ingenuity
以上文章節錄自 http://perl.plover.com/yak/hw-dcpm/
Monday, September 3, 2007
[微程式-技術研討會]xmpp(rfc-3920) 導讀
XMPP協定導讀
一. 什麼是jabber? 什麼是xmpp?
The Extensible Messaging and Presence Protocol (XMPP) is an open Extensible Markup Language XML [XML] protocol for near-real-time messaging, presence, and request-response services. The basic syntax and semantics were developed originally within the Jabber open-source community, mainly in 1999. In 2002, the XMPP WG was chartered with developing an adaptation of the Jabber protocol that would be suitable as an IETF instant messaging (IM) and presence technology. As a result of work by the XMPP WG, the current memo defines the core features of XMPP 1.0; the extensions required to provide the instant messaging and presence functionality defined in RFC 2779 [IMP REQS] are specified in Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence [XMPP IM].
二. Socket/XMPP 程式需注意的幾個重點
1.架構(select poll epoll AIO kqueue IOCP / Thread / Process / LWP)
2.setsockopt比較值得討論的參數
setsockopt( $listen,SOL_SOCKET,SO_REUSEADDR,1); 伺服端
setsockopt( $sockfd,SOL_SOCKET,SO_KEEPALIVE,pack("l",$SO_KEEPALIVE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPIDLE,pack( "l", $TCP_KEEPIDLE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPCNT,pack( "l", $TCP_KEEPCNT ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPINTVL,pack( "l", $TCP_KEEPINTVL ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_NODELAY,pack( "l", 1 ) );
setsockopt( $listen, SOL_SOCKET, SO_RCVBUF, 8192 );
setsockopt( $listen, SOL_SOCKET, SO_SNDBUF, 8192 );
3.flow(read/sysread/write/syswrite buffer)
4.XML Stream (SAX/DOM)
三. XMPP (RFC-3920 導讀)
1. XMPP 協定
Rfc-3920
Rfc-3921
Rfc-3922
Rfc-3923
Rfc-4622
可參考網站
http://www.xmpp.org/rfcs/
http://www.xmpp.org/extensions/
http://wiki.jabbercn.org/space/start
http://hi.baidu.com/jabber/blog/category/Jep
2. XML STREAM
<stream>
<presence>
<show/>
</presence>
<message to='foo'>
<body/>
</message>
<iq to='bar'>
<query/>
</iq>
…
</stream>
3. xmpp 的主要xml 標籤
訊息傳遞:<message/>
線上資訊:<presence/>
查詢與回應:<iq/>
目前實做的功能
<query xmlns=‘http://jabber.org/protocol/disco#info’>
<identity category='server' name='MJS' type='im'/>
<feature var='http://jabber.org/protocol/disco#info'/>
<feature var='http://jabber.org/protocol/disco#items'/>
<feature var='jabber:iq:private'/>
<feature var='jabber:iq:roster'/>
<feature var='jabber:iq:time'/>
<feature var='msgoffline'/>
</query>
4. 交易
以下定義
C->S 為CLIENT 傳送資料到 SERVER,
S->C 定義為伺服器傳遞資料給CLIENT,
Cn 代表第n個client
C1->S (Part1)
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
S->C1 (Part2)
<?xml version='1.0'?>
<stream:stream
from='127.0.0.1’
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
.認證與BINDING過程…(文件稍後會解釋交易過程) ,目前server不支援tls 的交易
C1->S
<message from='luke_shei@127.0.0.1/Resource1'
to=' admin@127.0.0.1/Resource2'
xml:lang='zh-tw' id=’R1-2’><body><測試訊息></body></message>
C1->S->C2(C1傳遞資訊給SERVER ,再經由JID 的資訊傳送給C2)
C2->S
<message from=' admin@127.0.0.1/Resource2'
to=' luke_shei@127.0.0.1/Resource1'
xml:lang='zh-tw' id=’R1-2’>
<body>回應訊息</body>
</message>
C2->S->C1(C2傳遞資訊給SERVER ,再經由JID 的資訊傳送給C1)
C1->S
</stream:stream>
S->C1
</stream:stream>
4.1 from/to 屬性:
a.C->S
b.S->C
Att /Action initiating to receiving receiving to initiating
to hostname of receiver silently ignored
From silently ignored hostname of receiver
id silently ignored session key
xml:lang default language default language
version signals XMPP 1.0 support signals XMPP 1.0 support
4.2 jid(Jabber Identifier) 形式:
a.node@domain/resource
b.node@domain
ps:事實上node 指的是用後帳號,目前;我們不支援將a,b 視為同一帳號的兩個不同的資
源binding,因此; node@domain/resource1 與node@domain/resource2 再目前的
系統是視為同一帳號的登入,而目前不支援同一帳號重覆登入
5. XMPP 需注意的事項
A. 內容替換
#x22 (")
#x26 (&)
#x27 (')
#x2F (/)
#x3A (:)
#x3C (<)
#x3E (>)
#x40 (@)
B. XML為case sensitive, 包括:認證所使用的UID
C.屬性皆以 ‘ 做為分隔
D.屬性是沒有順序性的
E.文件字集應該使用UTF-8
F.同一帳號應該以登入一次為限
G. 不應該預期交易的過程是否有斷行
I.Client 要斷線前,應保持良好習慣先傳遞
<presence type="unavailable"/></stream:stream> 再執行斷線
6. 認證交易(SASL RFC-2831)
(前略) 參考前述Part1 Part2
<Server 告知Client , 目前支援的認證型態>
S->C
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Ps:目前規劃使用的是 DIGEST-MD5 , PLAIN是為了讓SPARK(Jabber Client可以進行測試),而jabber::component 目前使用的是另一種handshark的機制
<Client 選擇一個認證機制>
C->S
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechani
sm='DIGEST-MD5'/>
Server 傳送challenge code
S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOX
RFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmL
TgsYWxnb3JpdGhtPW1kNS1zZXNzCg==</challenge>
中間這字串解開base 64 後的資訊為
realm="somerealm",nonce="OA6MG9tEQGm2hh",qop="auth",
charset=utf-8,algorithm=md5-sess
Client 傳送challenge code 給server
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlY
WxtIixub25jZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0i
T0E2TUhYaDZWcVRyUmsiLG5jPTAwMDAwMDAxLHFv
cD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5j
b20iLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwY
TE1MjMyMWYyMTQzYWY3LGNoYXJzZXQ9dXRmLTgK
</response>
中間字串的base64解碼為
username="somenode",realm="somerealm",nonce="
OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",
nc=00000001,qop=auth,digest-uri="xmpp/example.com"
,response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
<如驗證失敗 伺服器回應認證失敗>
S->C
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
隨即斷線
<伺服器傳送驗證碼>
S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cn
NwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJh
YmNkZmZmZAo=</challenge>
中間字串BASE64解碼為
rspauth=ea40f60335c427b5527b84dbabcdfffd
<CLIENT 回應驗證碼正確性>
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
<伺服器回應認證成功>
S->C
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
<認證成功後 Client 重新初始化 xml stream>
C->S
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
<伺服器回應所支援的feature>
S->C
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</stream:features>
<Client 請求Binding>
C->S
<iq id="jcl_8" type="set"><bind xmlns="urn:ietf:
params:xml:ns:xmpp-bind"><resource>Exodus<
/resource>
</bind></iq>
<伺服器回應Bind 的資源>
S->C
<iq type='result' id='jcl_8'><bind xmlns='urn:ietf:params
:xml:ns:xmpp-bind'><jid>admin@127.0.0.1/Exodus<
/jid><
/bind></iq>
<Client 請求session 交易>
C->S
<iq id="jcl_9" type="set"><session xmlns="urn:ietf:params:
xml:ns:xmpp-session"/></iq>
<Server 回應 session 交易>
S->C
<iq type='result' id='jcl_9'><session xmlns='urn:ietf:params:xml:
ns:xmpp-session'></session></iq>
5.認證演算過程
A. Server 傳送challenge code
S->C
BASE64(realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",
qop="auth", algorithm=md5-sess,charset=utf-8)
B. Client 傳送challenge code 給server
以下定義
開頭為$者為變數
開頭為 $$realm_xyz 代表該變數來自於realm 的屬性,而範例的值為xyz
以下範例 chris 為一個帳號名稱
+ 代表字串相加
‘ 代表固定字串內的值
MD5 代表其內字串使用MD5做簽章但不轉成HEX CODE
MD5_HEX 代表其內字串使用MD5做簽章且轉成HEX CODE
C->S
$PASSWORD 為該USER 的密碼
$A1=(MD5(‘chris’ + ‘:’ + $$realm_elwood.innosoft.com + ‘:’ + $PASSWORD) + ‘:’ + $$nonce _OA6MG9tEQGm2hh + ‘:’ + $$conce_OA6MHXh6VqTrRk)
$A2=’AUTHENTICATE’ + ‘:’ + $$realm_jabber/elwood.innosoft.com
$response=MD5_HEX(MD5_HEX($A1)+’:’+ $$nonce_OA6MG9tEQGm2hh +’:’+ $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk+’:’+ $$qop_auth +’:’ + MD5_HEX($A2))
Base64(charset=utf-8,username="chris",realm="elwood.innosoft.com", nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", digest-uri="jabber/elwood.innosoft.com",response=$response,qop=auth)
Server 隨即驗證 $response 如失敗則回傳失敗,否則進行下一個動作
C: 伺服器傳送驗證碼
rspauth=MD5_HEX(MD5_HEX($A1) + ‘:’ + $$nonce_OA6MG9tEQGm2hh + ’:’ + $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk + ’:’ + $$qop_auth+MD5_HEX(‘:’ + $$digest-uri _jabber/elwood.innosoft.com))
Client 應該檢驗 rspauth
七.相關資源
Jabber Client下載位置
Exodus ( http://www.jabberstudio.org/projects/exodus/releases/ )
Pandion( http://www.pandion.be/download/ )
Spaek( http://www.igniterealtime.org/downloads/download-landing.jsp?file=spark/spark_2_5_2.exe )
C 所常用的 XML parser library
http://expat.sourceforge.net/
msxml sax相關資源
http://www.perfectxml.com/msxmlSAX.asp
一. 什麼是jabber? 什麼是xmpp?
The Extensible Messaging and Presence Protocol (XMPP) is an open Extensible Markup Language XML [XML] protocol for near-real-time messaging, presence, and request-response services. The basic syntax and semantics were developed originally within the Jabber open-source community, mainly in 1999. In 2002, the XMPP WG was chartered with developing an adaptation of the Jabber protocol that would be suitable as an IETF instant messaging (IM) and presence technology. As a result of work by the XMPP WG, the current memo defines the core features of XMPP 1.0; the extensions required to provide the instant messaging and presence functionality defined in RFC 2779 [IMP REQS] are specified in Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence [XMPP IM].
二. Socket/XMPP 程式需注意的幾個重點
1.架構(select poll epoll AIO kqueue IOCP / Thread / Process / LWP)
2.setsockopt比較值得討論的參數
setsockopt( $listen,SOL_SOCKET,SO_REUSEADDR,1); 伺服端
setsockopt( $sockfd,SOL_SOCKET,SO_KEEPALIVE,pack("l",$SO_KEEPALIVE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPIDLE,pack( "l", $TCP_KEEPIDLE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPCNT,pack( "l", $TCP_KEEPCNT ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPINTVL,pack( "l", $TCP_KEEPINTVL ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_NODELAY,pack( "l", 1 ) );
setsockopt( $listen, SOL_SOCKET, SO_RCVBUF, 8192 );
setsockopt( $listen, SOL_SOCKET, SO_SNDBUF, 8192 );
3.flow(read/sysread/write/syswrite buffer)
4.XML Stream (SAX/DOM)
三. XMPP (RFC-3920 導讀)
1. XMPP 協定
Rfc-3920
Rfc-3921
Rfc-3922
Rfc-3923
Rfc-4622
可參考網站
http://www.xmpp.org/rfcs/
http://www.xmpp.org/extensions/
http://wiki.jabbercn.org/space/start
http://hi.baidu.com/jabber/blog/category/Jep
2. XML STREAM
<stream>
<presence>
<show/>
</presence>
<message to='foo'>
<body/>
</message>
<iq to='bar'>
<query/>
</iq>
…
</stream>
3. xmpp 的主要xml 標籤
訊息傳遞:<message/>
線上資訊:<presence/>
查詢與回應:<iq/>
目前實做的功能
<query xmlns=‘http://jabber.org/protocol/disco#info’>
<identity category='server' name='MJS' type='im'/>
<feature var='http://jabber.org/protocol/disco#info'/>
<feature var='http://jabber.org/protocol/disco#items'/>
<feature var='jabber:iq:private'/>
<feature var='jabber:iq:roster'/>
<feature var='jabber:iq:time'/>
<feature var='msgoffline'/>
</query>
4. 交易
以下定義
C->S 為CLIENT 傳送資料到 SERVER,
S->C 定義為伺服器傳遞資料給CLIENT,
Cn 代表第n個client
C1->S (Part1)
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
S->C1 (Part2)
<?xml version='1.0'?>
<stream:stream
from='127.0.0.1’
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
.認證與BINDING過程…(文件稍後會解釋交易過程) ,目前server不支援tls 的交易
C1->S
<message from='luke_shei@127.0.0.1/Resource1'
to=' admin@127.0.0.1/Resource2'
xml:lang='zh-tw' id=’R1-2’><body><測試訊息></body></message>
C1->S->C2(C1傳遞資訊給SERVER ,再經由JID 的資訊傳送給C2)
C2->S
<message from=' admin@127.0.0.1/Resource2'
to=' luke_shei@127.0.0.1/Resource1'
xml:lang='zh-tw' id=’R1-2’>
<body>回應訊息</body>
</message>
C2->S->C1(C2傳遞資訊給SERVER ,再經由JID 的資訊傳送給C1)
C1->S
</stream:stream>
S->C1
</stream:stream>
4.1 from/to 屬性:
a.C->S
b.S->C
Att /Action initiating to receiving receiving to initiating
to hostname of receiver silently ignored
From silently ignored hostname of receiver
id silently ignored session key
xml:lang default language default language
version signals XMPP 1.0 support signals XMPP 1.0 support
4.2 jid(Jabber Identifier) 形式:
a.node@domain/resource
b.node@domain
ps:事實上node 指的是用後帳號,目前;我們不支援將a,b 視為同一帳號的兩個不同的資
源binding,因此; node@domain/resource1 與node@domain/resource2 再目前的
系統是視為同一帳號的登入,而目前不支援同一帳號重覆登入
5. XMPP 需注意的事項
A. 內容替換
#x22 (")
#x26 (&)
#x27 (')
#x2F (/)
#x3A (:)
#x3C (<)
#x3E (>)
#x40 (@)
B. XML為case sensitive, 包括:認證所使用的UID
C.屬性皆以 ‘ 做為分隔
D.屬性是沒有順序性的
E.文件字集應該使用UTF-8
F.同一帳號應該以登入一次為限
G. 不應該預期交易的過程是否有斷行
I.Client 要斷線前,應保持良好習慣先傳遞
<presence type="unavailable"/></stream:stream> 再執行斷線
6. 認證交易(SASL RFC-2831)
(前略) 參考前述Part1 Part2
<Server 告知Client , 目前支援的認證型態>
S->C
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Ps:目前規劃使用的是 DIGEST-MD5 , PLAIN是為了讓SPARK(Jabber Client可以進行測試),而jabber::component 目前使用的是另一種handshark的機制
<Client 選擇一個認證機制>
C->S
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechani
sm='DIGEST-MD5'/>
Server 傳送challenge code
S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOX
RFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmL
TgsYWxnb3JpdGhtPW1kNS1zZXNzCg==</challenge>
中間這字串解開base 64 後的資訊為
realm="somerealm",nonce="OA6MG9tEQGm2hh",qop="auth",
charset=utf-8,algorithm=md5-sess
Client 傳送challenge code 給server
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlY
WxtIixub25jZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0i
T0E2TUhYaDZWcVRyUmsiLG5jPTAwMDAwMDAxLHFv
cD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5j
b20iLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwY
TE1MjMyMWYyMTQzYWY3LGNoYXJzZXQ9dXRmLTgK
</response>
中間字串的base64解碼為
username="somenode",realm="somerealm",nonce="
OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",
nc=00000001,qop=auth,digest-uri="xmpp/example.com"
,response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
<如驗證失敗 伺服器回應認證失敗>
S->C
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
隨即斷線
<伺服器傳送驗證碼>
S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cn
NwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJh
YmNkZmZmZAo=</challenge>
中間字串BASE64解碼為
rspauth=ea40f60335c427b5527b84dbabcdfffd
<CLIENT 回應驗證碼正確性>
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
<伺服器回應認證成功>
S->C
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
<認證成功後 Client 重新初始化 xml stream>
C->S
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
<伺服器回應所支援的feature>
S->C
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</stream:features>
<Client 請求Binding>
C->S
<iq id="jcl_8" type="set"><bind xmlns="urn:ietf:
params:xml:ns:xmpp-bind"><resource>Exodus<
/resource>
</bind></iq>
<伺服器回應Bind 的資源>
S->C
<iq type='result' id='jcl_8'><bind xmlns='urn:ietf:params
:xml:ns:xmpp-bind'><jid>admin@127.0.0.1/Exodus<
/jid><
/bind></iq>
<Client 請求session 交易>
C->S
<iq id="jcl_9" type="set"><session xmlns="urn:ietf:params:
xml:ns:xmpp-session"/></iq>
<Server 回應 session 交易>
S->C
<iq type='result' id='jcl_9'><session xmlns='urn:ietf:params:xml:
ns:xmpp-session'></session></iq>
5.認證演算過程
A. Server 傳送challenge code
S->C
BASE64(realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",
qop="auth", algorithm=md5-sess,charset=utf-8)
B. Client 傳送challenge code 給server
以下定義
開頭為$者為變數
開頭為 $$realm_xyz 代表該變數來自於realm 的屬性,而範例的值為xyz
以下範例 chris 為一個帳號名稱
+ 代表字串相加
‘ 代表固定字串內的值
MD5 代表其內字串使用MD5做簽章但不轉成HEX CODE
MD5_HEX 代表其內字串使用MD5做簽章且轉成HEX CODE
C->S
$PASSWORD 為該USER 的密碼
$A1=(MD5(‘chris’ + ‘:’ + $$realm_elwood.innosoft.com + ‘:’ + $PASSWORD) + ‘:’ + $$nonce _OA6MG9tEQGm2hh + ‘:’ + $$conce_OA6MHXh6VqTrRk)
$A2=’AUTHENTICATE’ + ‘:’ + $$realm_jabber/elwood.innosoft.com
$response=MD5_HEX(MD5_HEX($A1)+’:’+ $$nonce_OA6MG9tEQGm2hh +’:’+ $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk+’:’+ $$qop_auth +’:’ + MD5_HEX($A2))
Base64(charset=utf-8,username="chris",realm="elwood.innosoft.com", nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", digest-uri="jabber/elwood.innosoft.com",response=$response,qop=auth)
Server 隨即驗證 $response 如失敗則回傳失敗,否則進行下一個動作
C: 伺服器傳送驗證碼
rspauth=MD5_HEX(MD5_HEX($A1) + ‘:’ + $$nonce_OA6MG9tEQGm2hh + ’:’ + $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk + ’:’ + $$qop_auth+MD5_HEX(‘:’ + $$digest-uri _jabber/elwood.innosoft.com))
Client 應該檢驗 rspauth
七.相關資源
Jabber Client下載位置
Exodus ( http://www.jabberstudio.org/projects/exodus/releases/ )
Pandion( http://www.pandion.be/download/ )
Spaek( http://www.igniterealtime.org/downloads/download-landing.jsp?file=spark/spark_2_5_2.exe )
C 所常用的 XML parser library
http://expat.sourceforge.net/
msxml sax相關資源
http://www.perfectxml.com/msxmlSAX.asp
Tuesday, August 28, 2007
REST 相關文章表列
先由這裡開始吧!
用 SOAP 像 REST 一樣
http://blog.tcchou.org/Members/tcchou/tech/use_soap_as_rest
http://eoffice.im.fju.edu.tw/phpbb/viewtopic.php?p=11623
SIP/IMS網路中的Representational State Transfer (REST)
http://dev2dev.bea.com.cn/bbsdoc/20060529259.html
Building Web Services the REST Way
http://www.xfront.com/REST-Web-Services.html
Representational State Transfer
http://en.wikipedia.org/wiki/Representational_State_Transfer
How to Create a REST Protocol
http://www.xml.com/pub/a/2004/12/01/restful-web.html
用 SOAP 像 REST 一樣
http://blog.tcchou.org/Members/tcchou/tech/use_soap_as_rest
http://eoffice.im.fju.edu.tw/phpbb/viewtopic.php?p=11623
SIP/IMS網路中的Representational State Transfer (REST)
http://dev2dev.bea.com.cn/bbsdoc/20060529259.html
Building Web Services the REST Way
http://www.xfront.com/REST-Web-Services.html
Representational State Transfer
http://en.wikipedia.org/wiki/Representational_State_Transfer
How to Create a REST Protocol
http://www.xml.com/pub/a/2004/12/01/restful-web.html
Tuesday, August 21, 2007
一定要這樣玩弄技術名詞嗎?
xmpp erlang ...是什麼? 這些名詞不斷被提起,然而;這好像是在用嘴巴描述一件事不關己的事情,或是把它當成是飯後閒聊般的講述一次又一次沒有營養且毫無意義的東西,別這樣好嗎? 技術是需要深層的理解與思考的,沒有深度的探討 務實的探究 只是在浪費時間,無病呻吟是完全沒有意義的,技術的本身需要花時間去理解如果停滯不前,有再多的理由都沒有意義,不要一直在不著邊際的地方隔靴搔癢好嗎?這真是要不得的致命傷,無聊透頂了...
Sunday, August 12, 2007
erlang 會成為下一個java ?
Monday, August 6, 2007
我跟他的觀點截然不同
我跟他的觀點截然不同
從高鐵售票系統談大型公共建設軟體開發專案 (我一直在不斷的強調,真正高負載的系統是不會使用RDBMS的,而高鐵的問題是Critical Section的問題,跟系統本身使不使用RDB是完全無關的)
1.不要猜問題所在
一個大的系統出問題時;常常很難有一致的答案,有時候表面上看起來是那樣,改完後也確實改善問題,但事實上問題並不出在這邊,這樣的事情常常發生週而復始,因此;當系統出問題時,需要猜測問題的所在,而且應該假設有錯誤的地方不在表面上看到的那樣,最後需要一針見血的猜測(排除絕對不可能的部份,試圖讓問題縮小,然後找到最可能的原因),絕大部分的問題一開始我們都不能知道答案,尤其是我們往往假設,我們所使用的工具是正確的
2.解決問題的心態
這個觀點也是錯誤的,事實上開發人員並不是在大型專案中試煉自己的技能,不斷的調適、熟練的過程...,這些應該是平時應該要做的工作,因此;我們希望RD至少有1/3 的時間在做研究 2/3 的時間來作發展,事實上我們還希望把比例顛倒過來,當一個開發人員,有了純熟的技能,自然能夠避免犯下不可彌補的錯誤,甚至在開發的一開始就能避免很多不必要的浪費,而且能夠開發出強壯且靈活有深度的架構,因為他平常已經練習好,而且它有很多時間練習,而不是把作專案或是產品當成是練兵
========================================================
上回遇到NOVELL 的外聘開發人員,我把我自認為RD 為軟體公司核心的理論跟他交換意見,結果他卻要自斷經脈,他說RD通常不懂市場...,寫出來的東西不知道要賣給誰,我聽完當場昏倒,我想請教的是軟體公司的核心如果不在技術,而創造技術的不是RD ,那麼這家公司確定是軟體公司嗎? 一個出色的RD 必然理解市場脈動,至少他會有一個值得參考的產品技術觀點,只有三流的軟體開發人員才會自甘墮落淪為高級打字員心裡想著何時要轉為PM...,真正出色的工程師不僅解決問題,他還能引領整個公司的發展方向,我們要看5年後的技術將往哪發展,我們要創造公司的技術研發的沿革歷史,而不僅是今年公司要賺多少錢
從高鐵售票系統談大型公共建設軟體開發專案 (我一直在不斷的強調,真正高負載的系統是不會使用RDBMS的,而高鐵的問題是Critical Section的問題,跟系統本身使不使用RDB是完全無關的)
1.不要猜問題所在
一個大的系統出問題時;常常很難有一致的答案,有時候表面上看起來是那樣,改完後也確實改善問題,但事實上問題並不出在這邊,這樣的事情常常發生週而復始,因此;當系統出問題時,需要猜測問題的所在,而且應該假設有錯誤的地方不在表面上看到的那樣,最後需要一針見血的猜測(排除絕對不可能的部份,試圖讓問題縮小,然後找到最可能的原因),絕大部分的問題一開始我們都不能知道答案,尤其是我們往往假設,我們所使用的工具是正確的
2.解決問題的心態
這個觀點也是錯誤的,事實上開發人員並不是在大型專案中試煉自己的技能,不斷的調適、熟練的過程...,這些應該是平時應該要做的工作,因此;我們希望RD至少有1/3 的時間在做研究 2/3 的時間來作發展,事實上我們還希望把比例顛倒過來,當一個開發人員,有了純熟的技能,自然能夠避免犯下不可彌補的錯誤,甚至在開發的一開始就能避免很多不必要的浪費,而且能夠開發出強壯且靈活有深度的架構,因為他平常已經練習好,而且它有很多時間練習,而不是把作專案或是產品當成是練兵
========================================================
上回遇到NOVELL 的外聘開發人員,我把我自認為RD 為軟體公司核心的理論跟他交換意見,結果他卻要自斷經脈,他說RD通常不懂市場...,寫出來的東西不知道要賣給誰,我聽完當場昏倒,我想請教的是軟體公司的核心如果不在技術,而創造技術的不是RD ,那麼這家公司確定是軟體公司嗎? 一個出色的RD 必然理解市場脈動,至少他會有一個值得參考的產品技術觀點,只有三流的軟體開發人員才會自甘墮落淪為高級打字員心裡想著何時要轉為PM...,真正出色的工程師不僅解決問題,他還能引領整個公司的發展方向,我們要看5年後的技術將往哪發展,我們要創造公司的技術研發的沿革歷史,而不僅是今年公司要賺多少錢
Monday, July 30, 2007
[微程式-技術研討會]如何使用 flash player 開發應用程式
如何使用 網頁動畫 flash player 來開發應用程式 :
決定系統配置:
策略1: Microsoft- windows+ IIS +ASP+ (access 或 ms-sql server)
策略2. L.A.M.P.: Linux+ Apache + mysql + php
當然以上只是典型搭配法, OS, http-SERVER, Programming Language,DB
皆可視實際狀況抽換之.
再到網上搜尋 adobe macromedia flash開發環境:
Ex: 上軟體王 (http://www.softking.com.tw) ,打入以上字眼搜尋即可,
下載試用版來安裝; (含flash player)
***************************************************
執行架構簡述:
1. ActionScript:--
flash 自創的一套程式語言, 可用以控制動畫行為, 並與外部網頁連接通訊;
可用 javascript call flash- public- methods, 也可從 actionScript call javascript functions. 以下將舉例示範.
2. 對XML, server side-Script, GET/POST 的支援:-- (*本次的重點*)
這是最重要的一項應用, 傳統的網頁程式流程如下:
*****
Request -> http-SERVER -> Asp,Php…(讀寫db) -> (配合XSLT, 或html 輸出)
*****
由於 flash actionScript 可讀寫 XML, 並代替asp,php輸出 流程變成:
*****
Request(click flash動畫UI ) -> actionScript-calls (GET/POST) -> http-SERVER -> Asp,Php(讀寫db) -> 輸出XML -> flash 取回xml,並反映於動畫UI 上
*****
它實現了一種 全UI ,全動畫, no HTML的網站;
以下將舉例.
3. 支援 TCP/IP socket port 通訊 --
以下將示範一個以 flash 當client-ui, 實現一個免安裝,無reload 的聊天室.
*****************************************************
macromedia flash幾個優勢:
A 跨平台:--
flash player 播放器可 plug-in 在 IE, firefox 等網頁browser 之上,
並且有發行適用於ms-windows, Linux 等os 的安裝版本,
可至官網下載: (http://www.adobe.com/)
B 安裝性/安全性/介面性:
像是 activeX- OCX元件, 但flash跨平台, 免安裝, 不會引發 browser 安全性
的限制及詢問;
又像 java applet, 但java 作動畫麻煩, 而flash 本身就是動畫軟體;
C. 介面性/互動性:
介面看起來就像傳統的desktop-AP移到了browser上; 無換頁之感;
配合上flash 先天的動畫本領, 和user 的互動會更加良好;
***************************************************************
p.s: 所用到的 actionScript 指令參考:
a. 讀取/使用 xml data:
var RecordSet =new XML();
RecordSet.onLoad=LoadOK;
RecordSet.load( theAsp);
picPath= RecordSet.firstChild.childNodes[i].childNodes[9].firstChild.nodeValue
b. 送出get/post, 並取回結果:
var registerSend=new LoadVars();
registerSend.Email=myEmail.text;
registerSend.sendAndLoad("register.asp",registerLoad,"POST");
var registerLoad =new LoadVars();
registerLoad.onLoad=LoadOK;
c. flash Socket 通訊:
var myXMLSocket = new XMLSocket();
myXMLSocket.connect(null, 7890);
myXMLSocket.onConnect=myConnect;
myXMLSocket.onClose=myClose;
myXMLSocket.onXML=myOnData;
myXMLSocket.send(talkText.text + chr(0));
d. 網頁互動:
getURL("javascript: myInit();");
document.myFlash.TGotoFrame("_root",myFrame);
document.myFlash.play();
決定系統配置:
策略1: Microsoft- windows+ IIS +ASP+ (access 或 ms-sql server)
策略2. L.A.M.P.: Linux+ Apache + mysql + php
當然以上只是典型搭配法, OS, http-SERVER, Programming Language,DB
皆可視實際狀況抽換之.
再到網上搜尋 adobe macromedia flash開發環境:
Ex: 上軟體王 (http://www.softking.com.tw) ,打入以上字眼搜尋即可,
下載試用版來安裝; (含flash player)
***************************************************
執行架構簡述:
1. ActionScript:--
flash 自創的一套程式語言, 可用以控制動畫行為, 並與外部網頁連接通訊;
可用 javascript call flash- public- methods, 也可從 actionScript call javascript functions. 以下將舉例示範.
2. 對XML, server side-Script, GET/POST 的支援:-- (*本次的重點*)
這是最重要的一項應用, 傳統的網頁程式流程如下:
*****
Request -> http-SERVER -> Asp,Php…(讀寫db) -> (配合XSLT, 或html 輸出)
*****
由於 flash actionScript 可讀寫 XML, 並代替asp,php輸出 流程變成:
*****
Request(click flash動畫UI ) -> actionScript-calls (GET/POST) -> http-SERVER -> Asp,Php(讀寫db) -> 輸出XML -> flash 取回xml,並反映於動畫UI 上
*****
它實現了一種 全UI ,全動畫, no HTML的網站;
以下將舉例.
3. 支援 TCP/IP socket port 通訊 --
以下將示範一個以 flash 當client-ui, 實現一個免安裝,無reload 的聊天室.
*****************************************************
macromedia flash幾個優勢:
A 跨平台:--
flash player 播放器可 plug-in 在 IE, firefox 等網頁browser 之上,
並且有發行適用於ms-windows, Linux 等os 的安裝版本,
可至官網下載: (http://www.adobe.com/)
B 安裝性/安全性/介面性:
像是 activeX- OCX元件, 但flash跨平台, 免安裝, 不會引發 browser 安全性
的限制及詢問;
又像 java applet, 但java 作動畫麻煩, 而flash 本身就是動畫軟體;
C. 介面性/互動性:
介面看起來就像傳統的desktop-AP移到了browser上; 無換頁之感;
配合上flash 先天的動畫本領, 和user 的互動會更加良好;
***************************************************************
p.s: 所用到的 actionScript 指令參考:
a. 讀取/使用 xml data:
var RecordSet =new XML();
RecordSet.onLoad=LoadOK;
RecordSet.load( theAsp);
picPath= RecordSet.firstChild.childNodes[i].childNodes[9].firstChild.nodeValue
b. 送出get/post, 並取回結果:
var registerSend=new LoadVars();
registerSend.Email=myEmail.text;
registerSend.sendAndLoad("register.asp",registerLoad,"POST");
var registerLoad =new LoadVars();
registerLoad.onLoad=LoadOK;
c. flash Socket 通訊:
var myXMLSocket = new XMLSocket();
myXMLSocket.connect(null, 7890);
myXMLSocket.onConnect=myConnect;
myXMLSocket.onClose=myClose;
myXMLSocket.onXML=myOnData;
myXMLSocket.send(talkText.text + chr(0));
d. 網頁互動:
getURL("javascript: myInit();");
document.myFlash.TGotoFrame("_root",myFrame);
document.myFlash.play();
Friday, July 6, 2007
The factorial's tail recursive
Erlang:
-module(test).
-export([fac/1]).
fac(N) -> fac(N,1).
fac(0,A) -> A;
fac(N,A) -> fac(N-1,N*A).
--------------------------------
Haskell:
module Fac
where
fac(n)=facit(n,1)
facit(0,m) = m
facit(n,m)=facit(n-1,n*m)
-module(test).
-export([fac/1]).
fac(N) -> fac(N,1).
fac(0,A) -> A;
fac(N,A) -> fac(N-1,N*A).
--------------------------------
Haskell:
module Fac
where
fac(n)=facit(n,1)
facit(0,m) = m
facit(n,m)=facit(n-1,n*m)
一個Cluster/Grid Computing相關的線上論壇網站
http://pccluster.nchc.org.tw/xoops/modules/newbb/
一個Cluster/Grid Computing相關的線上論壇網站
一個Cluster/Grid Computing相關的線上論壇網站
Sunday, June 24, 2007
[微程式-技術研討會]微軟 asp.net 2.0 ajax
微軟Asp.net2.0 Ajax
一. Asp.net 2.0 Ajax
執行環境需求:
Framework 2.0
IIS
開發環境:
VS2005 C#.net (or VB.net)
微軟 Ajax 套件 (需另外下載)
1.下載套件:
http://ajax.asp.net/
於首頁 按下 Download ASP.NET AJAX v1.0
會進入下一個頁面
點下 Download ASP.NET Extensions V1.0 即可 下載
安裝完成後 開啟 VS2005
新增專案 選擇(VB 或 C#) Asp.net Ajax-Enabled Web Application
開啟後會發現 多了 1組元件在 工具箱 (Ajax Extensions)
2.介紹AJAX Extensions
ASP.NET AJAX v1.0 使用微軟自定的 Client Script Libery
1.ScriptManager控制項 – 整個 Asp.net Ajax 的核心 ,所有要使用Ajax的功能均必須使用該元件 ,負責建立User端的javascript ,使用Ajax功能時只能有一個ScriptManager控制項。
2.UpdatePanel控制項 – 與ScriptManager搭配使用後 ,可以簡單建立完成Ajax功能。
3.UpdateProgress控制項 – 與UpdatePanel 配合 ,用來顯示 非同步postback的處理狀況 ,或將非同步postback中斷。
4.Timer 控制項 – 就如同windows應用程式所使用的Timer 元件 ,可定時於page中重整 ,但時間設定太短可能會增加Server的負擔。
5.ScriptManagerProxy 控制項 – 在Asp.net Ajax的page裡只能用一個ScriptManager, 於Asp.net MasterPage(類似Html 的框架頁)會有多個Asp.net page,如果同時間有2個以上的網頁要使用Ajax功能需使用到 ScriptManager 則子版面必須使用ScriptManagerProxy
範例(一) AspNetAJAXdemo.aspx
配合 Asp.Net 2.0 的MasterPage 解說 這5大Asp.Net Ajax 控制項 的使用方式
二. Asp.Net Ajax Control Toolkit
Asp.Net Ajax Control Toolkit 為 Asp.Net Ajax 的強化套件 , 已有34項免費延伸元件可以直接使用,這件元件是由先前所介紹的那5個控制項所擴充而成
1. 下載
一樣至 http://ajax.asp.net/ 點選 Download ASP.NET AJAX v1.0 後出現以下畫面
點選 Download the ControlToolKit
2.新增至工具箱 加入索引 選擇項目 瀏覽 選擇剛剛下載的檔案裡位於 SampleWebSite\bin 中的 AjaxControlToolKit.dll
成功後工具箱將出現34種擴充元件可以使用
列舉幾個元件進行解說
1.TextBox 自動完成 (範例 AutoComplete.aspx)
AutoCompleteExtender
屬性:TargetControlID = 要被設定的TextBox 的ID
ServiceMethod = 後端所使用的Web Service( 或PageMethod)
ServicePath = WebService 的位置 , 不設定會自動判定使用 PageMethod
MinimumPrefixLength = 至少輸入多少字元後動作
CompletionInterval = 輸入多久後執行WebService的延遲時間(毫秒)
EnableCaching = 是否啟用 Caching
CompletionSetCount = 要回傳顯示的 item數
範例重點解說:
protected void Page_Load(object sender, EventArgs e) {
//設定 TargetControlID
AutoCompleteExtender1.TargetControlID = this.TextBox1.ID;
//輸入的字元長度
AutoCompleteExtender1.MinimumPrefixLength = 1;
//啟用Caching
AutoCompleteExtender1.EnableCaching = true;
//顯示的item數
AutoCompleteExtender1.CompletionSetCount = 15; //最多15筆
AutoCompleteExtender1.ServiceMethod = "GetEmailList";
}
//pageMethod
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static String[] GetEmailList(String prefixText,int count) {
//prefixText =輸入的字串 , count 要回傳的數目
//連結DB做過濾
String Constr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + @"D:\研討會Ajax\SolutionExp\Example2\DB\mail.mdb";
String sql = "select Top "+ count +" * from mail where mail like '"+ prefixText.Trim() +"%' order by mail";//取得mail清單
OleDbConnection conn = new OleDbConnection(Constr);
OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
DataTable dt = new DataTable();
da.Fill(dt);
String[] data = new string[dt.Rows.Count];
for (int i = 0; i < data.Length; i++) {
DataRow row = dt.Rows[i];
data[i] = row["mail"].ToString(); //取出mail
}
return data; //回傳String Array
}
2.自由拖曳panel(範例 DragPanel.aspx)
DragPanelExtender
屬性:TargetControlID = 要被拖曳的Panel 的ID
DragHandleID = 觸發拖曳事件的panel ID
*DragHandle 和 TargetControl 可為相同panel , 如不一樣,DragHandle的panel必須建立於TargetControl的panel 中
範例重點解說:
protected void Page_Load(object sender, EventArgs e) {
DragPanelExtender1.TargetControlID = this.Panel1.ID; // 要移動的panel;
DragPanelExtender1.DragHandleID = this.Panel2.ID;//觸發移動事件的panel;
this.Panel1.Style["cursor"] = "hand"; //滑鼠移到panel2 後游標變 成 hand
}
3.可拖曳放大縮小的網頁物件(範例 ResizableControl.aspx)
ResizableControl
屬性:
TargetControllID = 要改變大小的控制項
HandleCssClass = 拖曳點CSS設定
ResizableCssClass = 拖曳中的CSS設定
MinimunWidth = 拖曳時可接受的最小寬度
MinimunHeight = 拖曳時可接受的最小高度
MaxmumWidth = 拖曳時可接受的最大寬度
MaxmumHeight = 拖曳時可接受的最大高度
OnClientResize = 拖曳後要執行的javascript
OnClientResizing = 拖曳中要執行的javascript
OnClientResizeBegin = 拖曳前要執行的 javascript
HandleOffsetX = 拖曳點於物件右下角的X座標
HandleOffsetY = 拖曳點於物件右下角的Y座標
範例重點解說:
Css
<style type="text/css">
/* ResizableControl */
.frameImage
{
/* panel(圖片)大小 */
width:180px;
height:130px;
overflow:hidden;
float:left;
padding:3px;
}
.handleImage
{
/* 可拖曳圖示 */
width:15px;
height:16px;
background-image:url(Image/HandleHand.png);
overflow:hidden;
cursor:se-resize;
}
.resizingImage
{
padding:0px;
border-style:solid;
border-width:3px;
border-color:#B4D35D;
}
Javascript 抓取物件(panel1)大小 於Lable1中顯示
<script>
function onOK(){
$get('Label1').innerHTML=$get('Panel1').style.height + ',' + $get('Panel1').style.width;
}
</script>
主要程式碼
protected void Page_Load(object sender, EventArgs e) {
//拖曳圖示
ResizableControlExtender1.HandleCssClass = "handleImage";
//拖曳中的圖示
ResizableControlExtender1.ResizableCssClass = "resiaingImage";
//設定目標控制項
ResizableControlExtender1.TargetControlID = Panel1.ID;
//javascript function OnOK
ResizableControlExtender1.OnClientResize = "onOK";
//avascript function OnOK
ResizableControlExtender1.OnClientResizing = "onOK";
//最小高度
ResizableControlExtender1.MinimumHeight = 100;
//最小寬度
ResizableControlExtender1.MinimumWidth = 100;
}
4.Asp.net 2.0 Ajax應用 電子地圖
顯示頁面:DemoMap.aspx
處理頁面:GetMap.aspx
DemoMap.asp 程式碼
Javascript 在處理 拖曳panel 座標
<script type="text/javascript">
//位移變數
var offsetX,offsetY,startX,startY;
var isMoving; //開始移動Flag
function _start(){
//設定開始移動
isMoving=true;
//紀錄起點
startX=event.x;
startY=event.y;
startY=startY+17;
}
function _move(){
//如果在移動中模式
if (isMoving==true){
//移動
offsetX=event.x-startX;
offsetY=event.y-startY;
//設定圖檔位置
$get('Image1').style.left=10+(offsetX);
$get('Image1').style.top=130+(offsetY);
}
}
function _end(){
//如果在移動中模式
if (isMoving==true){
//設定處理完畢
isMoving=false;
//計算調整位移
offsetX=-(event.x-startX);
offsetY=-(event.y-startY);
offsetY= offsetY-17;
//以計算出的位移重新載入地圖
if (offsetX!=0 && offsetY!=0)
$get('Image1').src='GetMap.aspx?offsetX='+offsetX+'&offsetY='+offsetY+'&width=500&height=500';
$get('Image1').style.left=10;
$get('Image1').style.top=110;
}
}
</script>
DemoMap.aspx.cs
此function為在CS檔中直接定義 aspx中Panel_phantom 的Style 與javascrip操作事件
private void MakePhantom() {
Panel_phantom.Style["filter"] = "alpha(opacity=1);";
Panel_phantom.Style["cursor"] = "hand";
Panel_phantom.Style["position"] = "absolute";
Panel_phantom.Style["left"] = "15";
Panel_phantom.Style["top"] = "110";
Panel_phantom.Attributes["onmousedown"] = "_start();";
Panel_phantom.Attributes["onmouseup"] = "_end();";
Panel_phantom.Attributes["onmouseleave"] = "_end();";
Panel_phantom.Attributes["onmousemove"] = "_move();";
}
MapGotoXY 為 取得物件 Image1 的圖片來源 呼叫 GetMap.aspx 加上參數處理後,輸出所要顯示的圖片區塊
private void MapGotoXY(String x, String y) {
Image1.ImageUrl = "GetMap.aspx?x=" + x + "&y=" + y + "&width=500&height=500";
txb_x.Text = x ;
txb_y.Text = y ;
//設定拖曳用的Panel機制
MakePhantom();
}//MapGotoXY
GetMap.aspx
主要處理 地圖的顯示座標
protected void Page_Load(object sender, EventArgs e) {
//Image 的x,y 座標
int x =Convert.ToInt32(Request.QueryString["x"]);
int y =Convert.ToInt32( Request.QueryString["y"]);
//移動的 x,y座標
int offsetX = Convert.ToInt32(Request.QueryString["offsetX"]);
int offsetY = Convert.ToInt32(Request.QueryString["offsetY"]);
//地圖寬高
int width = Convert.ToInt32(Request.QueryString["width"]);
int height= Convert.ToInt32(Request.QueryString["height"]);
Bitmap bmp ;
Bitmap retbmp;
//讀入檔案
String ImgPath = Path.GetDirectoryName(Request.PhysicalPath) + @"\Image\tw.jpg";
bmp = new Bitmap(ImgPath);
if (x == 0 && y == 0 && offsetX != 0 && offsetY != 0) {
x = Convert.ToInt32(Session["_LastX"]) + offsetX;
y = Convert.ToInt32(Session["_LastY"])+ offsetY;
}
//防呆
if (x < 1) x = 1;
if (y < 1) y = 1;
if (x + width > bmp.Width) x = bmp.Width - width;
if (y + height > bmp.Height) y = bmp.Height - height;
//記錄 X,Y 座標
Session["_LastX"] = x;
Session["_LastY"] = y;
//宣告 GetMap 的輸出格式
Context.Response.ContentType= "image/Jpeg";
Context.Response.BufferOutput = false;
//建立矩形
Rectangle rect = new Rectangle(x, y, width, height);
retbmp = bmp.Clone(rect, bmp.PixelFormat); //取得圖片區塊
//處理圖形品質
System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
System.Drawing.Imaging.ImageCodecInfo ici = null;
//找出Encoder
foreach( System.Drawing.Imaging.ImageCodecInfo codec in codecs){
if( codec.MimeType == "image/jpeg") {
ici = codec;
}
}
//參數 - 高品質圖檔
System.Drawing.Imaging.EncoderParameters ep = new System.Drawing.Imaging.EncoderParameters();
ep.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, Convert.ToInt64(100));
retbmp.Save(Context.Response.OutputStream, ici, ep); //儲存
bmp.Dispose(); //釋放
retbmp.Dispose(); //釋放
Context.Response.End();//結束
}
5. 建立 統計圖
程式碼請參考
Chart..aspx
LineChart.cs
Chart..aspx主要顯示頁
LineChart.cs 為建立統計圖-點線圖的主要程式
輸出的圖 配合拖曳標籤可以自由移動圖表(使用DragPanelExtender)
如下方圖示
6. Ajax Excel圖表
程式碼過多 請參考
Excel_Demo.aspx
ExcelTable.cs
LineChart.cs
Excel_Demo.aspx 為主要顯示頁
背後處理程式有 ExcelTable.cs 與 LineChart.cs
ExcelTable.cs 提供3個funtion
1. reDrawExcelTable – 用來建立 table物件配合Javascript讓user感覺很像Excel
2. ExportDataTable –將Table轉化成DataTable提供給LineChart.cs
使LineChart 繪製圖片
3. SetValue – 初始化設定欄位的值
下圖為執行結果
Asp.Net2.0 配合 Ajax1.0 套件可以讓開發人員短時間之內,建出效果不錯的網頁,擴充元件讓頁面上只留下元件使用的標籤,除了微軟提供出的34項免費的基本元件可以使用外,也可以自行建立擴充元件 (Extender) , 至於要如何建立自訂的擴充元件,因為該功能步驟繁雜,等待小弟研究透徹後 ,有機會再向各位解說。
一. Asp.net 2.0 Ajax
執行環境需求:
Framework 2.0
IIS
開發環境:
VS2005 C#.net (or VB.net)
微軟 Ajax 套件 (需另外下載)
1.下載套件:
http://ajax.asp.net/
於首頁 按下 Download ASP.NET AJAX v1.0
會進入下一個頁面
點下 Download ASP.NET Extensions V1.0 即可 下載
安裝完成後 開啟 VS2005
新增專案 選擇(VB 或 C#) Asp.net Ajax-Enabled Web Application
開啟後會發現 多了 1組元件在 工具箱 (Ajax Extensions)
2.介紹AJAX Extensions
ASP.NET AJAX v1.0 使用微軟自定的 Client Script Libery
1.ScriptManager控制項 – 整個 Asp.net Ajax 的核心 ,所有要使用Ajax的功能均必須使用該元件 ,負責建立User端的javascript ,使用Ajax功能時只能有一個ScriptManager控制項。
2.UpdatePanel控制項 – 與ScriptManager搭配使用後 ,可以簡單建立完成Ajax功能。
3.UpdateProgress控制項 – 與UpdatePanel 配合 ,用來顯示 非同步postback的處理狀況 ,或將非同步postback中斷。
4.Timer 控制項 – 就如同windows應用程式所使用的Timer 元件 ,可定時於page中重整 ,但時間設定太短可能會增加Server的負擔。
5.ScriptManagerProxy 控制項 – 在Asp.net Ajax的page裡只能用一個ScriptManager, 於Asp.net MasterPage(類似Html 的框架頁)會有多個Asp.net page,如果同時間有2個以上的網頁要使用Ajax功能需使用到 ScriptManager 則子版面必須使用ScriptManagerProxy
範例(一) AspNetAJAXdemo.aspx
配合 Asp.Net 2.0 的MasterPage 解說 這5大Asp.Net Ajax 控制項 的使用方式
二. Asp.Net Ajax Control Toolkit
Asp.Net Ajax Control Toolkit 為 Asp.Net Ajax 的強化套件 , 已有34項免費延伸元件可以直接使用,這件元件是由先前所介紹的那5個控制項所擴充而成
1. 下載
一樣至 http://ajax.asp.net/ 點選 Download ASP.NET AJAX v1.0 後出現以下畫面
點選 Download the ControlToolKit
2.新增至工具箱 加入索引 選擇項目 瀏覽 選擇剛剛下載的檔案裡位於 SampleWebSite\bin 中的 AjaxControlToolKit.dll
成功後工具箱將出現34種擴充元件可以使用
列舉幾個元件進行解說
1.TextBox 自動完成 (範例 AutoComplete.aspx)
AutoCompleteExtender
屬性:TargetControlID = 要被設定的TextBox 的ID
ServiceMethod = 後端所使用的Web Service( 或PageMethod)
ServicePath = WebService 的位置 , 不設定會自動判定使用 PageMethod
MinimumPrefixLength = 至少輸入多少字元後動作
CompletionInterval = 輸入多久後執行WebService的延遲時間(毫秒)
EnableCaching = 是否啟用 Caching
CompletionSetCount = 要回傳顯示的 item數
範例重點解說:
protected void Page_Load(object sender, EventArgs e) {
//設定 TargetControlID
AutoCompleteExtender1.TargetControlID = this.TextBox1.ID;
//輸入的字元長度
AutoCompleteExtender1.MinimumPrefixLength = 1;
//啟用Caching
AutoCompleteExtender1.EnableCaching = true;
//顯示的item數
AutoCompleteExtender1.CompletionSetCount = 15; //最多15筆
AutoCompleteExtender1.ServiceMethod = "GetEmailList";
}
//pageMethod
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static String[] GetEmailList(String prefixText,int count) {
//prefixText =輸入的字串 , count 要回傳的數目
//連結DB做過濾
String Constr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + @"D:\研討會Ajax\SolutionExp\Example2\DB\mail.mdb";
String sql = "select Top "+ count +" * from mail where mail like '"+ prefixText.Trim() +"%' order by mail";//取得mail清單
OleDbConnection conn = new OleDbConnection(Constr);
OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
DataTable dt = new DataTable();
da.Fill(dt);
String[] data = new string[dt.Rows.Count];
for (int i = 0; i < data.Length; i++) {
DataRow row = dt.Rows[i];
data[i] = row["mail"].ToString(); //取出mail
}
return data; //回傳String Array
}
2.自由拖曳panel(範例 DragPanel.aspx)
DragPanelExtender
屬性:TargetControlID = 要被拖曳的Panel 的ID
DragHandleID = 觸發拖曳事件的panel ID
*DragHandle 和 TargetControl 可為相同panel , 如不一樣,DragHandle的panel必須建立於TargetControl的panel 中
範例重點解說:
protected void Page_Load(object sender, EventArgs e) {
DragPanelExtender1.TargetControlID = this.Panel1.ID; // 要移動的panel;
DragPanelExtender1.DragHandleID = this.Panel2.ID;//觸發移動事件的panel;
this.Panel1.Style["cursor"] = "hand"; //滑鼠移到panel2 後游標變 成 hand
}
3.可拖曳放大縮小的網頁物件(範例 ResizableControl.aspx)
ResizableControl
屬性:
TargetControllID = 要改變大小的控制項
HandleCssClass = 拖曳點CSS設定
ResizableCssClass = 拖曳中的CSS設定
MinimunWidth = 拖曳時可接受的最小寬度
MinimunHeight = 拖曳時可接受的最小高度
MaxmumWidth = 拖曳時可接受的最大寬度
MaxmumHeight = 拖曳時可接受的最大高度
OnClientResize = 拖曳後要執行的javascript
OnClientResizing = 拖曳中要執行的javascript
OnClientResizeBegin = 拖曳前要執行的 javascript
HandleOffsetX = 拖曳點於物件右下角的X座標
HandleOffsetY = 拖曳點於物件右下角的Y座標
範例重點解說:
Css
<style type="text/css">
/* ResizableControl */
.frameImage
{
/* panel(圖片)大小 */
width:180px;
height:130px;
overflow:hidden;
float:left;
padding:3px;
}
.handleImage
{
/* 可拖曳圖示 */
width:15px;
height:16px;
background-image:url(Image/HandleHand.png);
overflow:hidden;
cursor:se-resize;
}
.resizingImage
{
padding:0px;
border-style:solid;
border-width:3px;
border-color:#B4D35D;
}
Javascript 抓取物件(panel1)大小 於Lable1中顯示
<script>
function onOK(){
$get('Label1').innerHTML=$get('Panel1').style.height + ',' + $get('Panel1').style.width;
}
</script>
主要程式碼
protected void Page_Load(object sender, EventArgs e) {
//拖曳圖示
ResizableControlExtender1.HandleCssClass = "handleImage";
//拖曳中的圖示
ResizableControlExtender1.ResizableCssClass = "resiaingImage";
//設定目標控制項
ResizableControlExtender1.TargetControlID = Panel1.ID;
//javascript function OnOK
ResizableControlExtender1.OnClientResize = "onOK";
//avascript function OnOK
ResizableControlExtender1.OnClientResizing = "onOK";
//最小高度
ResizableControlExtender1.MinimumHeight = 100;
//最小寬度
ResizableControlExtender1.MinimumWidth = 100;
}
4.Asp.net 2.0 Ajax應用 電子地圖
顯示頁面:DemoMap.aspx
處理頁面:GetMap.aspx
DemoMap.asp 程式碼
Javascript 在處理 拖曳panel 座標
<script type="text/javascript">
//位移變數
var offsetX,offsetY,startX,startY;
var isMoving; //開始移動Flag
function _start(){
//設定開始移動
isMoving=true;
//紀錄起點
startX=event.x;
startY=event.y;
startY=startY+17;
}
function _move(){
//如果在移動中模式
if (isMoving==true){
//移動
offsetX=event.x-startX;
offsetY=event.y-startY;
//設定圖檔位置
$get('Image1').style.left=10+(offsetX);
$get('Image1').style.top=130+(offsetY);
}
}
function _end(){
//如果在移動中模式
if (isMoving==true){
//設定處理完畢
isMoving=false;
//計算調整位移
offsetX=-(event.x-startX);
offsetY=-(event.y-startY);
offsetY= offsetY-17;
//以計算出的位移重新載入地圖
if (offsetX!=0 && offsetY!=0)
$get('Image1').src='GetMap.aspx?offsetX='+offsetX+'&offsetY='+offsetY+'&width=500&height=500';
$get('Image1').style.left=10;
$get('Image1').style.top=110;
}
}
</script>
DemoMap.aspx.cs
此function為在CS檔中直接定義 aspx中Panel_phantom 的Style 與javascrip操作事件
private void MakePhantom() {
Panel_phantom.Style["filter"] = "alpha(opacity=1);";
Panel_phantom.Style["cursor"] = "hand";
Panel_phantom.Style["position"] = "absolute";
Panel_phantom.Style["left"] = "15";
Panel_phantom.Style["top"] = "110";
Panel_phantom.Attributes["onmousedown"] = "_start();";
Panel_phantom.Attributes["onmouseup"] = "_end();";
Panel_phantom.Attributes["onmouseleave"] = "_end();";
Panel_phantom.Attributes["onmousemove"] = "_move();";
}
MapGotoXY 為 取得物件 Image1 的圖片來源 呼叫 GetMap.aspx 加上參數處理後,輸出所要顯示的圖片區塊
private void MapGotoXY(String x, String y) {
Image1.ImageUrl = "GetMap.aspx?x=" + x + "&y=" + y + "&width=500&height=500";
txb_x.Text = x ;
txb_y.Text = y ;
//設定拖曳用的Panel機制
MakePhantom();
}//MapGotoXY
GetMap.aspx
主要處理 地圖的顯示座標
protected void Page_Load(object sender, EventArgs e) {
//Image 的x,y 座標
int x =Convert.ToInt32(Request.QueryString["x"]);
int y =Convert.ToInt32( Request.QueryString["y"]);
//移動的 x,y座標
int offsetX = Convert.ToInt32(Request.QueryString["offsetX"]);
int offsetY = Convert.ToInt32(Request.QueryString["offsetY"]);
//地圖寬高
int width = Convert.ToInt32(Request.QueryString["width"]);
int height= Convert.ToInt32(Request.QueryString["height"]);
Bitmap bmp ;
Bitmap retbmp;
//讀入檔案
String ImgPath = Path.GetDirectoryName(Request.PhysicalPath) + @"\Image\tw.jpg";
bmp = new Bitmap(ImgPath);
if (x == 0 && y == 0 && offsetX != 0 && offsetY != 0) {
x = Convert.ToInt32(Session["_LastX"]) + offsetX;
y = Convert.ToInt32(Session["_LastY"])+ offsetY;
}
//防呆
if (x < 1) x = 1;
if (y < 1) y = 1;
if (x + width > bmp.Width) x = bmp.Width - width;
if (y + height > bmp.Height) y = bmp.Height - height;
//記錄 X,Y 座標
Session["_LastX"] = x;
Session["_LastY"] = y;
//宣告 GetMap 的輸出格式
Context.Response.ContentType= "image/Jpeg";
Context.Response.BufferOutput = false;
//建立矩形
Rectangle rect = new Rectangle(x, y, width, height);
retbmp = bmp.Clone(rect, bmp.PixelFormat); //取得圖片區塊
//處理圖形品質
System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
System.Drawing.Imaging.ImageCodecInfo ici = null;
//找出Encoder
foreach( System.Drawing.Imaging.ImageCodecInfo codec in codecs){
if( codec.MimeType == "image/jpeg") {
ici = codec;
}
}
//參數 - 高品質圖檔
System.Drawing.Imaging.EncoderParameters ep = new System.Drawing.Imaging.EncoderParameters();
ep.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, Convert.ToInt64(100));
retbmp.Save(Context.Response.OutputStream, ici, ep); //儲存
bmp.Dispose(); //釋放
retbmp.Dispose(); //釋放
Context.Response.End();//結束
}
5. 建立 統計圖
程式碼請參考
Chart..aspx
LineChart.cs
Chart..aspx主要顯示頁
LineChart.cs 為建立統計圖-點線圖的主要程式
輸出的圖 配合拖曳標籤可以自由移動圖表(使用DragPanelExtender)
如下方圖示
6. Ajax Excel圖表
程式碼過多 請參考
Excel_Demo.aspx
ExcelTable.cs
LineChart.cs
Excel_Demo.aspx 為主要顯示頁
背後處理程式有 ExcelTable.cs 與 LineChart.cs
ExcelTable.cs 提供3個funtion
1. reDrawExcelTable – 用來建立 table物件配合Javascript讓user感覺很像Excel
2. ExportDataTable –將Table轉化成DataTable提供給LineChart.cs
使LineChart 繪製圖片
3. SetValue – 初始化設定欄位的值
下圖為執行結果
Asp.Net2.0 配合 Ajax1.0 套件可以讓開發人員短時間之內,建出效果不錯的網頁,擴充元件讓頁面上只留下元件使用的標籤,除了微軟提供出的34項免費的基本元件可以使用外,也可以自行建立擴充元件 (Extender) , 至於要如何建立自訂的擴充元件,因為該功能步驟繁雜,等待小弟研究透徹後 ,有機會再向各位解說。
Tuesday, June 5, 2007
socket 程式應該注意的參數
這幾天再寫jabber component 時發生一個奇怪的問題, 伺服器與component 固定一段時間就會終止通訊,然而連線此時還是存在的,伺服器或客乎端都沒有當掉,而且一般的jabber client 連接在上面也沒有問題,惟獨自己實做的server與client 無法通訊,後來發現;幾個socket 重要的參數,當client需要樣長時間連線時這些參數格外重要:
setsockopt SOL_SOCKET, SO_KEEPALIVE
setsockopt IPPROTO_TCP, TCP_KEEPIDLE
setsockopt IPPROTO_TCP, TCP_KEEPCNT
setsockopt IPPROTO_TCP, TCP_KEEPINTVL
程式再加了這些tcp 參數設定後,症狀完全消失
setsockopt SOL_SOCKET, SO_KEEPALIVE
setsockopt IPPROTO_TCP, TCP_KEEPIDLE
setsockopt IPPROTO_TCP, TCP_KEEPCNT
setsockopt IPPROTO_TCP, TCP_KEEPINTVL
程式再加了這些tcp 參數設定後,症狀完全消失
Saturday, May 26, 2007
perl v5.10 的相關資訊
http://pugs.blogs.com/talks/osdctw2007-perl510.pdf
看來這個承先啟後的版本做了不少的改變,在這些改變中,呵呵...台灣還佔有一席之地
看來這個承先啟後的版本做了不少的改變,在這些改變中,呵呵...台灣還佔有一席之地
Saturday, May 19, 2007
spamassassin v3.2 已釋出
其中比較有趣的是
1.
Mail::SpamAssassin::Spamd::Apache2 -- mod_perl2 module, implementing spamd as a mod_perl module, contributed as a Google Summer of Code project by Radoslaw Zielinski.
沒錯apache2 已不像過去,只是一個web server,他可以在上面發展其他的protocol,除了之前看過的smtp/ftp現在又多了spamd,但之前在apache2 上開發 lprd protocol 卻發現他的效率似乎沒有比自己寫伺服器來的好,至於穩不穩定,可能要有實際的數據支持
2.
sa-compile: compilation of SpamAssassin rules into a fast parallel-matching DFA, implemented in native code
這個技術我還沒時間仔細去trace,不過他應該是將spamassassin 使用的rules, 透過這個工具轉成c , 然後透過 xs 讓perl 來使用,這應該很有研究價值
1.
Mail::SpamAssassin::Spamd::Apache2 -- mod_perl2 module, implementing spamd as a mod_perl module, contributed as a Google Summer of Code project by Radoslaw Zielinski.
沒錯apache2 已不像過去,只是一個web server,他可以在上面發展其他的protocol,除了之前看過的smtp/ftp現在又多了spamd,但之前在apache2 上開發 lprd protocol 卻發現他的效率似乎沒有比自己寫伺服器來的好,至於穩不穩定,可能要有實際的數據支持
2.
sa-compile: compilation of SpamAssassin rules into a fast parallel-matching DFA, implemented in native code
這個技術我還沒時間仔細去trace,不過他應該是將spamassassin 使用的rules, 透過這個工具轉成c , 然後透過 xs 讓perl 來使用,這應該很有研究價值
Monday, April 30, 2007
xmpp 中文翻譯計畫 網站
http://wiki.jabbercn.org/space/start
另一個不錯的相關網站
http://hi.baidu.com/jabber/blog/category/Jep
iq:roster 的交易過程真是複雜的可以
http://64.233.179.104/translate_c?hl=zh-TW&sl=zh-CN&u=http://www.linuxboy.net/jabber/004.html&prev=/search%3Fq%3Diq:roster%26complete%3D1%26hl%3Dzh-TW%26pwst%3D1
另一個不錯的相關網站
http://hi.baidu.com/jabber/blog/category/Jep
iq:roster 的交易過程真是複雜的可以
http://64.233.179.104/translate_c?hl=zh-TW&sl=zh-CN&u=http://www.linuxboy.net/jabber/004.html&prev=/search%3Fq%3Diq:roster%26complete%3D1%26hl%3Dzh-TW%26pwst%3D1
Saturday, April 28, 2007
Concurrent Programming 相關報告
一. 我會接觸Erlang的緣由
1.RFID Middleware
2.jabber (xml::stream http://zh.wikipedia.org/wiki/Jabber)
3.ejabber (http://www.process-one.net/en/ )
二. 現在的商業環境(web server)所面臨的問題
1.連線的數量不斷的攀升
2.連線的時間很長
傳統上httpd 使用Prefork的方式來解決,短時間時密集連線的問題,在現在的環境愈到了嚴重的挑戰,比如: HTTP_Streaming、Server Push、COMET 這些需要長時間連線的架構,使得httpd 能夠服務的連線變少了,而fork process 最大的問題是,他所需要佔用記憶體的空間過於龐大,於是其他的伺服器架構崛起(lighthttpd ghttpd …)
The C10K problem( http://www.kegel.com/c10k.html )
It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now.
And computers are big, too. You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit/sec Ethernet card for $1200 or so. Let's see - at 20000 clients, that's 50KHz, 100Kbytes, and 50Kbits/sec per client. It shouldn't take any more horsepower than that to take four kilobytes from the disk and send them to the network once a second for each of twenty thousand clients. (That works out to $0.08 per client, by the way. Those $100/client licensing fees some operating systems charge are starting to look a little heavy!) So hardware is no longer the bottleneck???
三. Concurrent Programming
1. fork
原始的程式
(程式+資料) --fork(複製一份)(程式+資料)
當程式fork 後,child 繼承原來的資料,此後彼此不相關,如果要傳遞資訊,需要使用pipe sharememory 或是 unix socket 來做資料交換
2. thread
事實上在Linux 系統下,執行緒只是一個light weight process:Linux 核心是以fork() system call 來產生一個新的行程(process),而執行緒是以clone() system call 產生的。fork()和clone()的差別只是在clone()可以指定和父行程共用的資源有哪些,當所有資源都和父行程共用時就相當於一個執行緒了。因為Thread 的使用會讓子父行程共用資源,因此非常容易引發dead lock / race condition …這類的問題
3. lightweight Threads ( http://www.defmacro.org/ramblings/concurrency.html)
Erlang process 是一個輕量級的Thread,因此他可以非常輕易的去開啟或是結束且快速在彼此做切換,因為掀開他的底層,他只是一個簡單的function罷了,process節省了大量的context switching浪費僅在一些function上做切換的動作(Erlang 的Thread 是 vm level thread)
這份文件簡單的提到了Erlang的概觀
http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks
/252.pdf
四. Erlang ( http://www.erlang.org/ )
1.以下是 about Erlang 對他自己的簡述
Erlang is a programming language which has many features more commonly associated with an operating system than with a programming language: concurrent processes, scheduling, memory management, distribution, networking, etc.
The initial open-source Erlang release contains the implementation of Erlang, as well as a large part of Ericsson's middleware for building distributed high-availability systems.
Erlang is characterized by the following features:
Concurrency - Erlang has extremely lightweight processes whose memory requirements can vary dynamically. Processes have no shared memory and communicate by asynchronous message passing. Erlang supports applications with very large numbers of concurrent processes. No requirements for concurrency are placed on the host operating system.
Distribution - Erlang is designed to be run in a distributed environment. An Erlang virtual machine is called an Erlang node. A distributed Erlang system is a network of Erlang nodes (typically one per processor). An Erlang node can create parallel processes running on other nodes, which perhaps use other operating systems. Processes residing on different nodes communicate in exactly the same was as processes residing on the same node.
Soft real-time - Erlang supports programming "soft" real-time systems, which require response times in the order of milliseconds. Long garbage collection delays in such systems are unacceptable, so Erlang uses incremental garbage collection techniques.
Hot code upgrade - Many systems cannot be stopped for software maintenance. Erlang allows program code to be changed in a running system. Old code can be phased out and replaced by new code. During the transition, both old code and new code can coexist. It is thus possible to install bug fixes and upgrades in a running system without disturbing its operation.
Incremental code loading - Users can control in detail how code is loaded. In embedded systems, all code is usually loaded at boot time. In development systems, code is loaded when it is needed, even when the system is running. If testing uncovers bugs, only the buggy code need be replaced.
External interfaces - Erlang processes communicate with the outside world using the same message passing mechanism as used between Erlang processes. This mechanism is used for communication with the host operating system and for interaction with programs written in other languages. If required for reasons of efficiency, a special version of this concept allows e.g. C programs to be directly linked into the Erlang runtime system.
2.Erlang 語言上的概觀
書籍: ( http://pragmaticprogrammer.com/titles/jaerlang/index.html )
[ Sequential Erlang ]
Exam1:
Consider the factorial function N! defined by:
N!=N*(N-1) when N>0
N!=1 when N=0
-module(math1).
-export([fac/1]).
fac(N) when N > 0 -> N * fac(N-1);
fac(0)-> 1.
Exam2:
-module(math2).
-export([sum1/1, sum2/1]).
sum1([H T]) -> H + sum1(T);
sum1([]) -> 0.
sum2(L) -> sum2(L, 0).
sum2([], N) -> N;
sum2([H T], N) -> sum2(T, H+N).
[ Concurrency Programming ]
Exam3:
-module(concurrency).
-export([start/0, say /2]).
say (What, 0) ->
done;
say (What, Times) ->
io:format("~p~n", [What]),
say_something(What, Times - 1).
start() ->
spawn(tut14, say, [hello, 3]),
spawn(tut14, say, [goodbye, 3]).
Exam4:
-module(area_server).
-export([loop/0]).
loop() ->
receive
{rectangle, Width, Ht} ->
io:format("Area of rectangle is ~p~n",[Width * Ht]),
loop();
{circle, R} ->
io:format("Area of circle is ~p~n", [3.14159 * R * R]),
loop();
Other ->
io:format("I don't know what the area of a ~p is ~n",[Other]),
loop()
end.
We can create a process which evaluates loop/0 in the shell:
Pid = spawn(area_server,loop,[]).
Pid ! {rectangle, 6, 10}.
Pid ! {circle, 23}.
Pid ! {triangle,2,4,5}.
4. Erlang –style process or event-based model for actors ( http://lambda-the-ultimate.org/node/1615 )
( http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf )
Message passing
Each process has its own input queue for messages it receives. New messages received are put at the end of the queue. When a process executes a receive, the first message in the queue is matched against the first pattern in the receive, if this matches, the message is removed from the queue and the actions corresponding to the the pattern are executed.
However, if the first pattern does not match, the second pattern is tested, if this matches the message is removed from the queue and the actions corresponding to the second pattern are executed. If the second pattern does not match the third is tried and so on until there are no more pattern to test. If there are no more patterns to test, the first message is kept in the queue and we try the second message instead. If this matches any pattern, the appropriate actions are executed and the second message is removed from the queue (keeping the first message and any other messages in the queue). If the second message does not match we try the third message and so on until we reach the end of the queue. If we reach the end of the queue, the process blocks (stops execution) and waits until a new message is received and this procedure is repeated.
Of course the Erlang implementation is "clever" and minimizes the number of times each message is tested against the patterns in each receive.
五. Erlang相關資源
Website:
Open Source Erlang
http://www.erlang.org
http://www.process-one.net/en/projects/
Mail List:
Erlang-questions -- Erlang/OTP discussions
http://www.erlang.org/mailman/listinfo/erlang-questions
BOOK:
Concurrent programming in Erlang
http://www.erlang.org/download/erlang-book-part1.pdf
Programming Erlang Software for a Concurrent World
http://pragmaticprogrammer.com/titles/jaerlang/index.html
1.RFID Middleware
2.jabber (xml::stream http://zh.wikipedia.org/wiki/Jabber)
3.ejabber (http://www.process-one.net/en/ )
二. 現在的商業環境(web server)所面臨的問題
1.連線的數量不斷的攀升
2.連線的時間很長
傳統上httpd 使用Prefork的方式來解決,短時間時密集連線的問題,在現在的環境愈到了嚴重的挑戰,比如: HTTP_Streaming、Server Push、COMET 這些需要長時間連線的架構,使得httpd 能夠服務的連線變少了,而fork process 最大的問題是,他所需要佔用記憶體的空間過於龐大,於是其他的伺服器架構崛起(lighthttpd ghttpd …)
The C10K problem( http://www.kegel.com/c10k.html )
It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now.
And computers are big, too. You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit/sec Ethernet card for $1200 or so. Let's see - at 20000 clients, that's 50KHz, 100Kbytes, and 50Kbits/sec per client. It shouldn't take any more horsepower than that to take four kilobytes from the disk and send them to the network once a second for each of twenty thousand clients. (That works out to $0.08 per client, by the way. Those $100/client licensing fees some operating systems charge are starting to look a little heavy!) So hardware is no longer the bottleneck???
三. Concurrent Programming
1. fork
原始的程式
(程式+資料) --fork(複製一份)(程式+資料)
當程式fork 後,child 繼承原來的資料,此後彼此不相關,如果要傳遞資訊,需要使用pipe sharememory 或是 unix socket 來做資料交換
2. thread
事實上在Linux 系統下,執行緒只是一個light weight process:Linux 核心是以fork() system call 來產生一個新的行程(process),而執行緒是以clone() system call 產生的。fork()和clone()的差別只是在clone()可以指定和父行程共用的資源有哪些,當所有資源都和父行程共用時就相當於一個執行緒了。因為Thread 的使用會讓子父行程共用資源,因此非常容易引發dead lock / race condition …這類的問題
3. lightweight Threads ( http://www.defmacro.org/ramblings/concurrency.html)
Erlang process 是一個輕量級的Thread,因此他可以非常輕易的去開啟或是結束且快速在彼此做切換,因為掀開他的底層,他只是一個簡單的function罷了,process節省了大量的context switching浪費僅在一些function上做切換的動作(Erlang 的Thread 是 vm level thread)
這份文件簡單的提到了Erlang的概觀
http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks
/252.pdf
四. Erlang ( http://www.erlang.org/ )
1.以下是 about Erlang 對他自己的簡述
Erlang is a programming language which has many features more commonly associated with an operating system than with a programming language: concurrent processes, scheduling, memory management, distribution, networking, etc.
The initial open-source Erlang release contains the implementation of Erlang, as well as a large part of Ericsson's middleware for building distributed high-availability systems.
Erlang is characterized by the following features:
Concurrency - Erlang has extremely lightweight processes whose memory requirements can vary dynamically. Processes have no shared memory and communicate by asynchronous message passing. Erlang supports applications with very large numbers of concurrent processes. No requirements for concurrency are placed on the host operating system.
Distribution - Erlang is designed to be run in a distributed environment. An Erlang virtual machine is called an Erlang node. A distributed Erlang system is a network of Erlang nodes (typically one per processor). An Erlang node can create parallel processes running on other nodes, which perhaps use other operating systems. Processes residing on different nodes communicate in exactly the same was as processes residing on the same node.
Soft real-time - Erlang supports programming "soft" real-time systems, which require response times in the order of milliseconds. Long garbage collection delays in such systems are unacceptable, so Erlang uses incremental garbage collection techniques.
Hot code upgrade - Many systems cannot be stopped for software maintenance. Erlang allows program code to be changed in a running system. Old code can be phased out and replaced by new code. During the transition, both old code and new code can coexist. It is thus possible to install bug fixes and upgrades in a running system without disturbing its operation.
Incremental code loading - Users can control in detail how code is loaded. In embedded systems, all code is usually loaded at boot time. In development systems, code is loaded when it is needed, even when the system is running. If testing uncovers bugs, only the buggy code need be replaced.
External interfaces - Erlang processes communicate with the outside world using the same message passing mechanism as used between Erlang processes. This mechanism is used for communication with the host operating system and for interaction with programs written in other languages. If required for reasons of efficiency, a special version of this concept allows e.g. C programs to be directly linked into the Erlang runtime system.
2.Erlang 語言上的概觀
書籍: ( http://pragmaticprogrammer.com/titles/jaerlang/index.html )
[ Sequential Erlang ]
Exam1:
Consider the factorial function N! defined by:
N!=N*(N-1) when N>0
N!=1 when N=0
-module(math1).
-export([fac/1]).
fac(N) when N > 0 -> N * fac(N-1);
fac(0)-> 1.
Exam2:
-module(math2).
-export([sum1/1, sum2/1]).
sum1([H T]) -> H + sum1(T);
sum1([]) -> 0.
sum2(L) -> sum2(L, 0).
sum2([], N) -> N;
sum2([H T], N) -> sum2(T, H+N).
[ Concurrency Programming ]
Exam3:
-module(concurrency).
-export([start/0, say /2]).
say (What, 0) ->
done;
say (What, Times) ->
io:format("~p~n", [What]),
say_something(What, Times - 1).
start() ->
spawn(tut14, say, [hello, 3]),
spawn(tut14, say, [goodbye, 3]).
Exam4:
-module(area_server).
-export([loop/0]).
loop() ->
receive
{rectangle, Width, Ht} ->
io:format("Area of rectangle is ~p~n",[Width * Ht]),
loop();
{circle, R} ->
io:format("Area of circle is ~p~n", [3.14159 * R * R]),
loop();
Other ->
io:format("I don't know what the area of a ~p is ~n",[Other]),
loop()
end.
We can create a process which evaluates loop/0 in the shell:
Pid = spawn(area_server,loop,[]).
Pid ! {rectangle, 6, 10}.
Pid ! {circle, 23}.
Pid ! {triangle,2,4,5}.
4. Erlang –style process or event-based model for actors ( http://lambda-the-ultimate.org/node/1615 )
( http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf )
Message passing
Each process has its own input queue for messages it receives. New messages received are put at the end of the queue. When a process executes a receive, the first message in the queue is matched against the first pattern in the receive, if this matches, the message is removed from the queue and the actions corresponding to the the pattern are executed.
However, if the first pattern does not match, the second pattern is tested, if this matches the message is removed from the queue and the actions corresponding to the second pattern are executed. If the second pattern does not match the third is tried and so on until there are no more pattern to test. If there are no more patterns to test, the first message is kept in the queue and we try the second message instead. If this matches any pattern, the appropriate actions are executed and the second message is removed from the queue (keeping the first message and any other messages in the queue). If the second message does not match we try the third message and so on until we reach the end of the queue. If we reach the end of the queue, the process blocks (stops execution) and waits until a new message is received and this procedure is repeated.
Of course the Erlang implementation is "clever" and minimizes the number of times each message is tested against the patterns in each receive.
五. Erlang相關資源
Website:
Open Source Erlang
http://www.erlang.org
http://www.process-one.net/en/projects/
Mail List:
Erlang-questions -- Erlang/OTP discussions
http://www.erlang.org/mailman/listinfo/erlang-questions
BOOK:
Concurrent programming in Erlang
http://www.erlang.org/download/erlang-book-part1.pdf
Programming Erlang Software for a Concurrent World
http://pragmaticprogrammer.com/titles/jaerlang/index.html
Labels:
active rfid,
Concurrent Programming,
Erlang,
RFID,
RFID MIDDLEWARE,
主動式rfid,
微程式技術研討會,
微程式資訊股份有限公司,
技術研討會
Tuesday, April 24, 2007
xmpp 實做的分享
最近在寫jabber server, jabber 是建構在xmpp protocol 上的一個IM,因為RFC的規格制定曠日費時,所以;jabber 以xmpp 為基礎,自己又定義了約200 個協定XEP-0001~0214,而 xmpp 主要由五個protocol所組成,分別是RFC-3920~3923 RFC-4622
我目前的進度已經可以讓像 Exodus or Pandion(IM Client) 連接上我自己實做的jabber server,預計下星期我就能讓im client 直接在上面talk,且訂閱彼此的狀態...在寫的過程成中越來越覺得他的複雜,其實,這大概是我目前寫過最複雜的伺服器,不過有一點心得可以先分享給大家,其實有一些人有一個疑問,jabber長的像什麼? 如果我們撇開他在IM的實做(處理訊息的傳遞也是一種運算資源),我們可以把它看成是一家公司,一家公司會有他對客戶的服務,而當產品要製作時,它需要資源,需要應徵人員,每個應徵的人員需要依照公司的制度來運行(component plug-in),每個人員應徵後需要報到,然後正式工作,依照給個人的專業知識分派工作 ....循環不已,當新的產品要製作時,這個公司可以再應徵新的 不同專業領域的資源,而且可以重新制定新的工作規則...而公司組織裡的這些運行其實都是靠制度,而這個制度相對於jabber 就是他的protocol,所以我把xmpp形容成是一個資源/運算的分散者,因此他可以建構一個基本的Grid Computing 環境,把每個運算工作分散到無限台機器上....如果你要問他可以做什麼? 事實上在jabber 的protocol 裡幾乎定義了絕大部分
的應用,voip 影音...,所有的運算資源都可以在事後 plug in 進去,google_talk 所實做的部份可能還不到整個jabber 的1/20,由此;我們可以看出他的規模/擴充性之大... 總之把他想成是一個有組織的公司,只是公司的規模有大有小罷了,xmpp 的工作資源分配真的跟這個描述很像,有機會自己實做一次體會一下囉!
我目前的進度已經可以讓像 Exodus or Pandion(IM Client) 連接上我自己實做的jabber server,預計下星期我就能讓im client 直接在上面talk,且訂閱彼此的狀態...在寫的過程成中越來越覺得他的複雜,其實,這大概是我目前寫過最複雜的伺服器,不過有一點心得可以先分享給大家,其實有一些人有一個疑問,jabber長的像什麼? 如果我們撇開他在IM的實做(處理訊息的傳遞也是一種運算資源),我們可以把它看成是一家公司,一家公司會有他對客戶的服務,而當產品要製作時,它需要資源,需要應徵人員,每個應徵的人員需要依照公司的制度來運行(component plug-in),每個人員應徵後需要報到,然後正式工作,依照給個人的專業知識分派工作 ....循環不已,當新的產品要製作時,這個公司可以再應徵新的 不同專業領域的資源,而且可以重新制定新的工作規則...而公司組織裡的這些運行其實都是靠制度,而這個制度相對於jabber 就是他的protocol,所以我把xmpp形容成是一個資源/運算的分散者,因此他可以建構一個基本的Grid Computing 環境,把每個運算工作分散到無限台機器上....如果你要問他可以做什麼? 事實上在jabber 的protocol 裡幾乎定義了絕大部分
的應用,voip 影音...,所有的運算資源都可以在事後 plug in 進去,google_talk 所實做的部份可能還不到整個jabber 的1/20,由此;我們可以看出他的規模/擴充性之大... 總之把他想成是一個有組織的公司,只是公司的規模有大有小罷了,xmpp 的工作資源分配真的跟這個描述很像,有機會自己實做一次體會一下囉!
Friday, April 20, 2007
Tuesday, April 17, 2007
Saturday, April 14, 2007
javascript 縮減語法的工具
http://dean.edwards.name/packer/
這是一個javascript 縮減語法的工具,他的原理其實就是把 javascript 內不必要的斷行 空白...去除,這個網站還提供php .net ...的語法縮減工具,縮減語法的好處可以降低網路頻寬的使用,參考google 的首頁就知道,google 不只把js 縮減,也把html 也縮減了,這樣可以節省大量網頁下載時所使用的頻寬
另外google 還會對輸出網頁做gzip 的壓縮,這一點我就比較不明白,事實上;使用cache 的機制會比做gzip來的更節省(http hrader: cache-control expire if-modify-since etag...尤其是針對不常變動的首頁),然而;ie 6 有一個bug,那就是當網頁使用gzip 時,上述的標頭都會失效(firefox 則不會有此問題),因此;這一點是我比較不解的地方
這是一個javascript 縮減語法的工具,他的原理其實就是把 javascript 內不必要的斷行 空白...去除,這個網站還提供php .net ...的語法縮減工具,縮減語法的好處可以降低網路頻寬的使用,參考google 的首頁就知道,google 不只把js 縮減,也把html 也縮減了,這樣可以節省大量網頁下載時所使用的頻寬
另外google 還會對輸出網頁做gzip 的壓縮,這一點我就比較不明白,事實上;使用cache 的機制會比做gzip來的更節省(http hrader: cache-control expire if-modify-since etag...尤其是針對不常變動的首頁),然而;ie 6 有一個bug,那就是當網頁使用gzip 時,上述的標頭都會失效(firefox 則不會有此問題),因此;這一點是我比較不解的地方
Subscribe to:
Posts (Atom)