傳輸(Transports) 定義了和套接字交互的接口app
Ranch 的傳輸層抽象了兩個協議處理模塊出來, 一個是用於普通的TCP傳輸層套接字 ranch_tcp
, 另外一個是SSL加密傳輸層套接字處理模塊 ranch_ssl
socket
傳輸可用於鏈接(connecting
), 監聽(listenig
), 以及接受(accepting
)鏈接, 也能夠接收(receiving
)和發送(sending
)數據.tcp
支持主動(active
)和被動(passive
)模式函數
TCP 傳輸是一個 gen_tcp
的輕量級封裝.atom
SSL 傳輸是一個 ssl
的輕量級封裝. 它依賴於 Erlang 提供的 crypto
,asn1
,public_key
和ssl
應用程序, 所以必須在 Ranch 以前啓動. 當啓動一個 SSL 監聽器的時候, Ranch 會自動的啓動他們. 監聽器刪除的時候, 不會中止他們,加密
啓動 SSL 應用code
ssl:start().
在一個正確的 OTP 設置中, 你須要保證你的應用程序依賴 crypto
, public_key
和 ssl
應用程序. 當啓動你的 release 時, 他們會被自動啓動.orm
SSL 傳輸的 accept/2
函數同時執行傳輸(transport
)和SSL 接受(SSL accepts
)的操做. 在SSL接受階段若是發生錯誤, 將返回 {error, {ssl_accept, atom()}}
以區分問題發生在哪一個套接字上.接口
能夠經過 Transport:send/2
函數給套接字發送數據. 數據的類型爲 iodata()
, 它包含兩種子類型 binary() | iolist()
進程
經過套接字發送數據
Transport:send(Socket, <<"Ranch is cool!">>). Transport:send(Socket, "Ranch is cool!"). Transport:send(Socket, ["Ranch", ["is", "cool!"]]). Transport:send(Socket, ["Ranch", [<<"is">>, "cool!"]]).
能夠經過被動模式
或主動模式
接收數據. 被動模式執行阻塞的 Transport:recv/3
調用. 主動模式把數據做爲消息接收.
默認全部數據是做爲二進制接收的. 也能夠把接收的數據當成字符串.
用被動模式接收數據要求一個函數調用. 第一個參數爲套接字, 第三個參數爲讀取超時值(超時後返回{error, timeout}
.
第二個參數爲想要接收的數據字節數. 該函數將會等待數據, 直到它接收到了指定長度的數據. 若是不指定精確的值, 也能夠指定爲0 , 它會盡快的返回, 而無論數據的大小.
被動模式下,從套接字讀取數據
{ok, Data} = Transport:recv(Socket, 0, 5000).
主動模式要求你告知套接字你想要把數據做爲消息接收, 而且編寫代碼來接收消息.
主動模式有兩種類型 {active, once}
和 {active, true}
, 前者發送一個消息後就當即回到被動模式. 後者無限地發送消息. 不推薦使用 {active, true}
模式, 這種模式會很快的把進程郵箱塞滿. 更好的是, 把數據留在套接字中, 僅當須要的時候再讀取.
能夠接收三種不懂的消息
{OK, Socket, Data}
{Closed, Socket}
{Error, Socket, Reason}
取決於選擇的傳輸模塊, OK
, Closed
, 和 Error
的值有可能不一樣. 要可以正確的匹配他們, 必須首先調用 Transport:messages/0
函數.
獲取傳輸的主動消息標識
{OK, Closed, Error} = Transport:messages().
要開始接收消息, 你須要調用 Transport:setopts/2
函數, 而且每次再接收消息的時候都要這樣作.
主動模式下, 從套接字接收消息
{OK, Closed, Error} = Transport:messages(), Transport:setopts(Socket, [{active, once}]), receive {OK, Socket, Data} -> io:format("data received: ~p~n", [Data]); {Closed, Socket} -> io:format("socket got closed!~n"); {Error, Socket, Reason} -> io:format("error happended: ~p~n", [Reason]) end.
能夠很容易的把主動套接字集成到 Erlang 代碼中, 當接收消息時, 僅僅須要很少的代碼.
經過套接字發送名爲 Filename
的文件:
經過文件名發送文件
{OK, SentBytes} = Transport:sendfile(Socket, Filename).
若是是文件的一部分, 使用大於等於0的Offset
, Bytes
字節數, 以及 ChunkSize
塊大小:
發送文件的一部分塊
Opts = [{chunk_size, ChunkSize}] {ok, SentBytes} = Transport:sendfile(Socket, Filename, Offset, Bytes, Opts).
要改善發送同一個文件的多個部分, 可使用以raw
模式打開的文件描述符:
發送一個以 raw 模式打開的文件
{ok, RawFile} = file:open(Filename, [raw, read, binary]), {ok, SentBytes} = Transport:sendfile(Socket, RawFile, Offset, Bytes, Opts).
傳輸處理模塊是一個實現了 ranch_transport
行爲的模塊(好比(ranch_tcp
, ranch_ssl
).
ranch_tcp.erl
文件頭兩行說明了這個事實
-module(ranch_tcp). -behaviour(ranch_transport).
爲了可以透明的使用傳輸處理模塊, 須要行爲中定義的一系列回調函數.
當打開套接字時, 該行爲沒有定義可用的套接字選項. 由於對於使用不一樣的傳輸, 編寫不一樣的初始化函數是至關容易的, 所以不須要有共同的傳輸選項設置, 一個例外是, setopts/2
必須 實現 {active, once}
和 {active, true}
選項
若是傳輸沒有實現 sendfile/5
, 將使用 ranch_transport:sendfile/6
替代. 多的第一個參數是傳輸模塊. 例子能夠參考 ranch_ssl
模塊.