監聽的定義: 服務器等待
來自任意遠端的鏈接請求.node
這張圖的信息量很大, 能夠仔細研究. 圖中頂部黃色的 LISTEN 方塊就是監聽器的所處的位置. git
一個監聽器是一組進程, 它的用途是在一個指定的端口上監聽新的TCP鏈接. 它管理着一個接收器進程池, 池中的每一個接收器一直持續不斷的接受鏈接. 當一個新的鏈接到達時, 它啓動一個新的進程來執行協議處理代碼, 全部的套接字編程經過使用傳輸處理模塊進行抽象.github
監聽器關注於監控全部的接收器和鏈接進程, 容許開發者把關注點放在構建應用程序上.編程
默認 Ranch 什麼都不會作, 要求 Ranch 監聽鏈接是應用開發者的事情. segmentfault
監聽器能夠啓動和中止, 當啓動一個監聽器的時候, 要求許多不一樣的設置:服務器
一個本地的標識名稱, 經過這個名稱能與監聽器交互.併發
資源池中的接收器的數量.app
一個傳輸處理器以及關聯的選項.負載均衡
一個協議處理器以及關聯的選項.dom
Ranch 包括 TCP 和 SSL 傳輸處理器, 分別爲 ranch_tcp
和 ranch_ssl
模塊.
監聽器能夠經過調用 ranch:start_listener/6
函數來啓動, 在這以前, 請確保 ranch
應用程序已經啓動.
啓動 Ranch 應用程序
ok = application:start(ranch).
如今就能夠啓動監聽器了, 給這個監聽器一個名字, 叫他 tcp_echo
. 它有一個包含 100 個接收器的資源池, 使用TCP傳輸, 並轉發鏈接到 echo_protolcol
處理器.
在端口 5555 啓動一個監聽器
{ok, _} = ranch:start_listener( tcp_echo, %% 監聽器的名稱 100, %% 100 個 Acceptors ranch_tcp, %% 使用TCP傳輸 [{port, 5555}], %% 監聽器選項 echo_protocol, %% 協議處理模塊 [] %% 協議處理模塊選項 ).
能夠在項目目錄的 examples
目錄測試並編譯運行 tcp_echo
這個例子. 打開終端在 examples/tcp_echo
目錄下運行下面的命令:
$ make run
能夠經過 telnet
命令鏈接並查看服務器的響應. 可用 Ctrl+]
組合鍵轉義 telnet 命令行, 並輸入 quit
退出.
使用 telnet 鏈接到監聽器
$ telnet localhost 5555 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello! Hello! It works! It works! ^] telnet> quit Connection closed.
只須要調用 ranch:stop_listener/1
函數中止一個監聽器, 它接受一個監聽器的名字做爲參數, 以前使用名稱 tcp_echo
啓動了這個監聽器, 如今中止它.
中止一個監聽器
ranch:stop_listener(tcp_echo).
默認套接字設置爲使用 {active, false}, {packet, raw}, {reuseaddr, true}
選項返回 binary
數據. 這些選項能夠在啓動監聽器的時候覆蓋, 同時也能夠在協議處理模塊中調用 Transport:setopts/2
來覆蓋.
It will also set
{backlog, 1024}
and{nodelay, true}
, which can be overriden at listener startup.
若是還要設置 {backlog, 1024}
和 {nodelay, true}
, 在監聽器啓動的時候能夠覆蓋.
You do not have to specify a specific port to listen on. If you give the port number 0, or if you omit the port number entirely, Ranch will start listening on a random port.
若是在監聽的時候沒必要指定端口, 若是你指定端口爲 0
, 或者徹底省略端口號, Ranch 將監聽在隨機端口上.
You can retrieve this port number by calling ranch:get_port/1. The argument is the name of the listener you gave in ranch:start_listener/6.
能夠嗲用 ranch:get_port/1
獲取端口號, 參數爲 監聽器的名稱, 即: 啓動監聽器是傳遞給 ranch:start_listener/6
的第一個參數.
Starting a listener for TCP connections on a random port {ok, _} = ranch:start_listener(tcp_echo, 100, ranch_tcp, [{port, 0}], echo_protocol, [] ). Port = ranch:get_port(tcp_echo).
Some systems limit access to ports below 1024 for security reasons. This can easily be identified by an {error, eacces} error when trying to open a listening socket on such a port.
1024 一下的端口在多數 Linux/Unix 系統上都要求具備 Root 權限, 若是你沒有 Root 權限, 在 1024 一下打開一個監聽套接字的時候, 將會拋出錯誤 {error, eacces}
.
The methods for listening on privileged ports vary between systems, please refer to your system’s documentation for more information.
不一樣的系統, 在特權端口上監聽都不大相同, 細節請參考系統文檔
We recommend the use of port rewriting for systems with a single server, and load balancing for systems with multiple servers. Documenting these solutions is however out of the scope of this guide.
推薦單服務器使用端口從新, 多服務器使用負載均衡. 這些方案與本文無關就不作討論了.
若是想要在已經存在的套接字上接受鏈接, 可使用 socket
傳輸選項. 對於傳輸或套接字庫(gen_tcp:connect
, ssl:connect
), 其應該只是從鏈接函數返回的相關的數據. accept 函數調用傳入的套接字. 應該以 {active, false}
模式鏈接套接字.
由於SSL的BUG, 在R16以前, 沒法改變一個SSL監聽套接字的全部權. SSL套接字的建立者做爲該套接字的全部者, 並不影響 accept 行爲,除非該套接字的全部者掛了.
max_connections
傳輸選項容許限制併發鏈接的數量. 默認爲 1024
, 目的是防止系統過載, 以保證全部的鏈接都可以的快速的處理.
自定義最大併發鏈接數
{ok, _} = ranch:start_listener(tcp_echo, 100, ranch_tcp, [{port, 5555}, {max_connections, 100}], echo_protocol, [] ).
能夠經過設置併發鏈接數爲 infinity
禁用併發鏈接限制(不推薦)
{ok, _} = ranch:start_listener(tcp_echo, 100, ranch_tcp, [{port, 5555}, {max_connections, infinity}], echo_protocol, [] ).
在某些狀況下, 並不老是指望某個鏈接被計入 max_connections
, 例如長鏈接和短鏈接混用的時候.
要刪除鏈接計數, 從鏈接進程內調用 ranch:remove_connection/1
, 惟一的參數爲監聽器的名字.
ranch:remove_connection(Ref).
能夠經過 ranch:set_max_connections/2
設置監聽器的最大鏈接數
ranch:set_max_connections(tcp_echo, MaxConns).
修改即時生效.
Ranch allows you to define the type of process that will be used for the connection processes. By default it expects a worker. When the connection_type configuration value is set to supervisor, Ranch will consider that the connection process it manages is a supervisor and will reflect that in its supervision tree.
Ranch 能夠定義用於鏈接進程的進程類型. 默認爲 worker
類型. 當 connection_type
的值設置爲 supervisor
時, Ranch 會認爲它所管理的鏈接進程是一個 Supervisor, 而且掛載到監控樹中.
Connection processes of type supervisor can either handle the socket directly or through one of their children. In the latter case the start function for the connection process must return two pids: the pid of the supervisor you created (that will be supervised) and the pid of the protocol handling process (that will receive the socket).
supervisor
類型的鏈接進程可以直接處理
套接字, 或者經過其子進程處理
套接字. 對於經過其子進程處理
套接字, 鏈接進程的 start 函數必須返回兩個 pid: 你建立的 supervisor
的 (被監聽器監控的) pid 和 協議處理進程的 pid(接收套接字).
Instead of returning {ok, ConnPid}, simply return {ok, SupPid, ConnPid}.
這種狀況下, 返回的 是 {ok, SupPid, ConnPid}
而不是 {ok, ConnPid}
It is very important that the connection process be created under the supervisor process so that everything works as intended. If not, you will most likely experience issues when the supervised process is stopped.
Ranch 容許在運行時升級協議選項. 這對後續的鏈接立馬生效.
要升級協議選項, 須要調用 ranch:set_protocol_options/2
函數, 監聽器的名稱做爲第一個參數, 新的選項做爲第二個參數.
升級協議選項
ranch:set_protocol_options(tcp_echo, NewOpts).
全部後續創建的鏈接將會使用新的選項
也能夠調用 ranch:get_protocol_options/1
獲取當前的協議選項.
獲取當前的協議選項
Opts = ranch:get_protocol_options(tcp_echo).
https://github.com/ninenines/ranch/blob/master/doc/src/guide/listeners.asciidoc
https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Protocol_operation