Browse Source

st: 格式化

master
SisMaker 3 years ago
parent
commit
69beeb1d8b
13 changed files with 222 additions and 224 deletions
  1. +1
    -0
      README.md
  2. +22
    -18
      include/proxyPt.hrl
  3. +2
    -2
      src/eNet_app.erl
  4. +105
    -112
      src/misc/erlang套接字编程和性能优化.md
  5. +11
    -11
      src/misc/ntCidr.erl
  6. +20
    -20
      src/misc/ntCom.erl
  7. +1
    -1
      src/misc/ntTBucket.erl
  8. +1
    -1
      src/proxyPt/ntPptAcceptorSup.erl
  9. +2
    -2
      src/proxyPt/nt_proxy_protocol.erl
  10. +1
    -1
      src/tcp/ntTcpAcceptor.erl
  11. +6
    -6
      src/test/utTcpAFSrv.erl
  12. +25
    -25
      src/test/utTcpCli.erl
  13. +25
    -25
      src/test/utUdpCli.erl

+ 1
- 0
README.md View File

@ -1,4 +1,5 @@
# eNet # eNet
erlang网络库 erlang网络库
{ok, Pid} = eNet:addTcpLr(test11, {{127,0,0, 1}, 9010}, echo_server, [{tcpOpts, [binary, {packet, 2}, {active, false}]}]). {ok, Pid} = eNet:addTcpLr(test11, {{127,0,0, 1}, 9010}, echo_server, [{tcpOpts, [binary, {packet, 2}, {active, false}]}]).

+ 22
- 18
include/proxyPt.hrl View File

@ -5,29 +5,33 @@
%% Proxy-Protocol Socket Wrapper %% Proxy-Protocol Socket Wrapper
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-type(pp2_additional_ssl_field() :: {pp2_ssl_client, boolean()}
| {pp2_ssl_client_cert_conn, boolean()}
| {pp2_ssl_client_cert_sess, boolean()}
| {pp2_ssl_verify, success | failed}
| {pp2_ssl_version, binary()} % US-ASCII string
| {pp2_ssl_cn, binary()} % UTF8-encoded string
| {pp2_ssl_cipher, binary()} % US-ASCII string
| {pp2_ssl_sig_alg, binary()} % US-ASCII string
| {pp2_ssl_key_alg, binary()}).% US-ASCII string
-type(pp2_additional_ssl_field() :: {pp2_ssl_client, boolean()}
| {pp2_ssl_client_cert_conn, boolean()}
| {pp2_ssl_client_cert_sess, boolean()}
| {pp2_ssl_verify, success | failed}
| {pp2_ssl_version, binary()} % US-ASCII string
| {pp2_ssl_cn, binary()} % UTF8-encoded string
| {pp2_ssl_cipher, binary()} % US-ASCII string
| {pp2_ssl_sig_alg, binary()} % US-ASCII string
| {pp2_ssl_key_alg, binary()} % US-ASCII string
).
-type(pp2_additional_field() :: {pp2_alpn, binary()} % byte sequence
| {pp2_authority, binary()} % UTF8-encoded string
| {pp2_crc32c, integer()} % 32-bit number
| {pp2_netns, binary()} % US-ASCII string
| {pp2_ssl, list(pp2_additional_ssl_field())}).
-type(pp2_additional_field() ::
{pp2_alpn, binary()} % byte sequence
| {pp2_authority, binary()} % UTF8-encoded string
| {pp2_crc32c, integer()} % 32-bit number
| {pp2_netns, binary()} % US-ASCII string
| {pp2_ssl, list(pp2_additional_ssl_field())}
).
-record(proxy_socket, { -record(proxy_socket, {
inet = inet4 :: inet4 | inet6 | 'unix' | 'unspec',
src_addr = {0,0,0,0} :: inet:ip_address() | undefined,
dst_addr = {0,0,0,0} :: inet:ip_address() | undefined,
inet = inet4 :: inet4 | inet6 | 'unix' | 'unspec',
src_addr = {0, 0, 0, 0} :: inet:ip_address() | undefined,
dst_addr = {0, 0, 0, 0} :: inet:ip_address() | undefined,
src_port = 0 :: inet:port_number() | undefined, src_port = 0 :: inet:port_number() | undefined,
dst_port = 0 :: inet:port_number() | undefined, dst_port = 0 :: inet:port_number() | undefined,
%% Proxy protocol v2 addtional fields %% Proxy protocol v2 addtional fields
pp2_additional_info = [] :: list(pp2_additional_field())}).
pp2_additional_info = [] :: list(pp2_additional_field())
}).
-endif. -endif.

+ 2
- 2
src/eNet_app.erl View File

@ -5,8 +5,8 @@
-export([start/2, stop/1]). -export([start/2, stop/1]).
start(_StartType, _StartArgs) -> start(_StartType, _StartArgs) ->
eNet_sup:start_link().
eNet_sup:start_link().
stop(_State) -> stop(_State) ->
ok.
ok.

+ 105
- 112
src/misc/erlang套接字编程和性能优化.md View File

@ -1,4 +1,5 @@
#### erlang 各种 优化设置
#### erlang 各种 优化设置
一、 erl启动时参数: 一、 erl启动时参数:
+K true 开启epoll调度,在linux中开启epoll,会大大增加调度的效率 +K true 开启epoll调度,在linux中开启epoll,会大大增加调度的效率
+A 100 异步线程池,为某些port调用服 +A 100 异步线程池,为某些port调用服
@ -92,8 +93,9 @@
发送高低水位:{high_watermark, 128 * 1024} | {low_watermark, 64 * 1024},辅助delay_send使用,delay_send的聚合缓冲区大小为high_watermark,数据缓存到high_watermark后,将阻塞port_command,使用send发送数据,直到缓冲区大小降低到low_watermark后,解除阻塞,通常这些值越大越好,但erlang虚拟机允许设置的最大值不超过128K 发送高低水位:{high_watermark, 128 * 1024} | {low_watermark, 64 * 1024},辅助delay_send使用,delay_send的聚合缓冲区大小为high_watermark,数据缓存到high_watermark后,将阻塞port_command,使用send发送数据,直到缓冲区大小降低到low_watermark后,解除阻塞,通常这些值越大越好,但erlang虚拟机允许设置的最大值不超过128K
发送缓冲大小:{sndbuf, 16 * 1024},操作系统对套接字的发送缓冲大小,在延迟发送时有效,越大越好,但有极值 发送缓冲大小:{sndbuf, 16 * 1024},操作系统对套接字的发送缓冲大小,在延迟发送时有效,越大越好,但有极值
接收缓冲大小:{recbuf, 16 * 1024},操作系统对套接字的接收缓冲大小 接收缓冲大小:{recbuf, 16 * 1024},操作系统对套接字的接收缓冲大小
#### Erlang 虚拟机调优 #### Erlang 虚拟机调优
目录 目录
SMP SMP
Schedulers Schedulers
@ -109,38 +111,27 @@
Shutdown Time Shutdown Time
Riak 是用Erlang语言写的,运行在Erlang虚拟机之上.所以Erlang虚拟机的调优对Riak的性能优化就显得尤为重要. Erlang虚拟机本身提供了非常多的配置参数对性能调优, Riak支持其中的一部分参数,你可以在每个node的Riak配置文件中进行设置. Riak 是用Erlang语言写的,运行在Erlang虚拟机之上.所以Erlang虚拟机的调优对Riak的性能优化就显得尤为重要. Erlang虚拟机本身提供了非常多的配置参数对性能调优, Riak支持其中的一部分参数,你可以在每个node的Riak配置文件中进行设置.
下表列出了其中的一部分,左边一列是Erlang中的参数名称, 右边一列是在Riak中的参数名称. Erlang parameter Riak parameter +A erlang.async_threads +K erlang.K +P
erlang.process_limit +Q erlang.max_ports +S erlang.schedulers.total, erlang.schedulers.online +W erlang.W +a
erlang.async_threads.stack_size +e erlang.max_ets_tables +scl erlang.schedulers.compaction_of_load +sfwi
erlang.schedulers.force_wakeup_interval -smp erlang.smp +sub erlang.schedulers.utilization_balancing +zdbbl
erlang.distribution_buffer_size -kernel net_ticktime erlang.distribution.net_ticktime -env FULLSWEEP_AFTER
erlang.fullsweep_after -env ERL_CRASH_DUMP erlang.crash_dump -env ERL_MAX_ETS_TABLES erlang.max_ets_tables -name
nodename Note on upgrading to 2.0 在Riak2.0版本之前, Erlang虚拟机相关的参数放在配置文件 vm.args 里面. 在2.0及之后的版本中, 所有Erlang虚拟机相关的配置参数放在配置文件
riak.conf 里面. 如果你从Riak2.0之前的版本升级到Riak 2.0, 你仍然可以继续使用旧的配置文件 vm.args. 但是, 如果你同时设置了配置文件 vm.args 和riak.conf, 在
vm.args里面的配置将会覆盖riak.conf里面的配置.
##### SMP
下表列出了其中的一部分,左边一列是Erlang中的参数名称, 右边一列是在Riak中的参数名称.
Erlang parameter Riak parameter
+A erlang.async_threads
+K erlang.K
+P erlang.process_limit
+Q erlang.max_ports
+S erlang.schedulers.total, erlang.schedulers.online
+W erlang.W
+a erlang.async_threads.stack_size
+e erlang.max_ets_tables
+scl erlang.schedulers.compaction_of_load
+sfwi erlang.schedulers.force_wakeup_interval
-smp erlang.smp
+sub erlang.schedulers.utilization_balancing
+zdbbl erlang.distribution_buffer_size
-kernel net_ticktime erlang.distribution.net_ticktime
-env FULLSWEEP_AFTER erlang.fullsweep_after
-env ERL_CRASH_DUMP erlang.crash_dump
-env ERL_MAX_ETS_TABLES erlang.max_ets_tables
-name nodename
Note on upgrading to 2.0
在Riak2.0版本之前, Erlang虚拟机相关的参数放在配置文件 vm.args 里面. 在2.0及之后的版本中, 所有Erlang虚拟机相关的配置参数放在配置文件 riak.conf 里面. 如果你从Riak2.0之前的版本升级到Riak 2.0, 你仍然可以继续使用旧的配置文件 vm.args. 但是, 如果你同时设置了配置文件 vm.args 和riak.conf, 在 vm.args里面的配置将会覆盖riak.conf里面的配置.
##### SMP
有些操作系统提供Erlang虚拟机对称多处理器能力(SMP)以利用多处理器硬件架构的优势. SMP的支持可以通过设置erlang.smp参数来打开和关闭, 默认是打开的. 下面的例子是关闭SMP的支持. 有些操作系统提供Erlang虚拟机对称多处理器能力(SMP)以利用多处理器硬件架构的优势. SMP的支持可以通过设置erlang.smp参数来打开和关闭, 默认是打开的. 下面的例子是关闭SMP的支持.
riak.conf riak.conf
erlang.smp = disable erlang.smp = disable
由于Riak也可以运行在一些不支持SMP的操作系统上, 所以在使用之前需要确认操作系统是否支持SMP,如果操作系统本身不支持,那么需要在启动Riak集群之前在配置文件riak.conf中关闭SMP的选项. 由于Riak也可以运行在一些不支持SMP的操作系统上, 所以在使用之前需要确认操作系统是否支持SMP,如果操作系统本身不支持,那么需要在启动Riak集群之前在配置文件riak.conf中关闭SMP的选项.
比较安全的一个选择是把erlang.smp设置成auto, 这个选项会指示Erlang虚拟机启动SMP支持之前检查操作系统是否支持以及是否有一个以上的逻辑处理器,只有这两个条件都满足的时候,Erlang虚拟机才启动SMP支持. 比较安全的一个选择是把erlang.smp设置成auto, 这个选项会指示Erlang虚拟机启动SMP支持之前检查操作系统是否支持以及是否有一个以上的逻辑处理器,只有这两个条件都满足的时候,Erlang虚拟机才启动SMP支持.
##### Schedulers ##### Schedulers
Note on missing scheduler flags Note on missing scheduler flags
We recommend that all users set the +sfwi to 500 (milliseconds) and the +sclflag to false if using the older, vm.args-based configuration system. If you are using the new, riak.conf-based configuration system, the corresponding parameters are erlang.schedulers.force_wakeup_interval anderlang.schedulers.compaction_of_load. We recommend that all users set the +sfwi to 500 (milliseconds) and the +sclflag to false if using the older, vm.args-based configuration system. If you are using the new, riak.conf-based configuration system, the corresponding parameters are erlang.schedulers.force_wakeup_interval anderlang.schedulers.compaction_of_load.
Please note that you will need to uncomment the appropriate lines in your riak.conf for this configuration to take effect. Please note that you will need to uncomment the appropriate lines in your riak.conf for this configuration to take effect.
@ -151,72 +142,86 @@ Note on upgrading to 2.0
如果两个参数中的任意一个被设置成负数, 那么意味着这个参数值将会被设成默认配置的处理器数量(如果scheduler.total是负数)或者可用的处理器数量(如果schedulers.online是负数) 减去配置的负值. 比如, 如果机器配置有100个cpu(cores)然后参数schedulers.total配置为-50, 计算以后的值就是50. 如果两个参数中的任意一个被设置成负数, 那么意味着这个参数值将会被设成默认配置的处理器数量(如果scheduler.total是负数)或者可用的处理器数量(如果schedulers.online是负数) 减去配置的负值. 比如, 如果机器配置有100个cpu(cores)然后参数schedulers.total配置为-50, 计算以后的值就是50.
如果两个参数中的任意一个被设置为0,两个值都会被重新设为默认值. 如果两个参数中的任意一个被设置为0,两个值都会被重新设为默认值.
如果SMP支持被关闭, 比如erlang.smp被设成disabled或者设成auto 但是机器本身不支持SMP或者机器只有一个逻辑处理器,那么两个参数schedulers.total 和 schedulers.online都将会被忽略. 如果SMP支持被关闭, 比如erlang.smp被设成disabled或者设成auto 但是机器本身不支持SMP或者机器只有一个逻辑处理器,那么两个参数schedulers.total 和 schedulers.online都将会被忽略.
Scheduler Wakeup Interval
调度器唤醒是一个可选处理, 通过这个Erlang 虚拟机调度器被周期性的扫描来判定是否已经陷入睡眠, 比如是否调度器有一个空的运行列表. 这个扫描时间间隔可以通过参数erlang.schedulers.force_wakeup_interval设置, 单位为毫秒.这个参数对应于Erlang虚拟机的+sfwi选项.该参数默认设为0, 不激活调度器唤醒功能.
Erlang在R15Bx版本里有把调度器睡眠过于频繁的倾向,如果你使用的是更新的版本,比如Riak2.0 及以后, 那多数情况下不需要启动唤醒功能.
注: OTP的工程师曾经解释过这个功能,如果需要调度的任务不是很多,没有很多task在运行列表上的话, R15B的Erlang虚拟机会倾向于把这些task尽量集中到尽可能少的调度器上来调度, 睡眠没有调度任务的调度器, 这样可以减少调度器之间的通信花费overhead, 提高CPU的利用率. 但这个也是一个trade off, 具体还是需要用户来根据自己的实际环境来调优. 因为一旦task的数量增加比较多,或者task数量没有增加但是task本身比较耗时,那么很可能就会触发调度器的唤醒, 而唤醒调度器是比较expensive的操作, 如果频繁睡眠唤醒的话,可能会得不偿失.
##### Scheduler Compaction and Balancing
Scheduler Wakeup Interval 调度器唤醒是一个可选处理, 通过这个Erlang 虚拟机调度器被周期性的扫描来判定是否已经陷入睡眠, 比如是否调度器有一个空的运行列表.
这个扫描时间间隔可以通过参数erlang.schedulers.force_wakeup_interval设置, 单位为毫秒.这个参数对应于Erlang虚拟机的+sfwi选项.该参数默认设为0, 不激活调度器唤醒功能.
Erlang在R15Bx版本里有把调度器睡眠过于频繁的倾向,如果你使用的是更新的版本,比如Riak2.0 及以后, 那多数情况下不需要启动唤醒功能. 注:
OTP的工程师曾经解释过这个功能,如果需要调度的任务不是很多,没有很多task在运行列表上的话, R15B的Erlang虚拟机会倾向于把这些task尽量集中到尽可能少的调度器上来调度, 睡眠没有调度任务的调度器,
这样可以减少调度器之间的通信花费overhead, 提高CPU的利用率. 但这个也是一个trade off, 具体还是需要用户来根据自己的实际环境来调优.
因为一旦task的数量增加比较多,或者task数量没有增加但是task本身比较耗时,那么很可能就会触发调度器的唤醒, 而唤醒调度器是比较expensive的操作, 如果频繁睡眠唤醒的话,可能会得不偿失.
##### Scheduler Compaction and Balancing
Erlang调度器提供了两种方式来分发负载到不同的调度器上, 集中负载和utilization balancing. Erlang调度器提供了两种方式来分发负载到不同的调度器上, 集中负载和utilization balancing.
集中负载是默认打开的, 打开的时候Erlang虚拟机会尝试去尽可能多的使调度器繁忙,比如通过把任务集中到有限的几个调度器上(假设这几个有限的调度器充分运行的情况下可以调度完目前的tasks)使这几个调度器一直有工作做(not run out of work). 为了达到这个目的, 当虚拟机分配任务的时候会考虑哪些调度器应该被分配任务. 用户可以设置参数erlang.schedulers.compaction_of_load为false来关闭这个功能. 集中负载是默认打开的, 打开的时候Erlang虚拟机会尝试去尽可能多的使调度器繁忙,比如通过把任务集中到有限的几个调度器上(假设这几个有限的调度器充分运行的情况下可以调度完目前的tasks)使这几个调度器一直有工作做(not run out of work). 为了达到这个目的, 当虚拟机分配任务的时候会考虑哪些调度器应该被分配任务. 用户可以设置参数erlang.schedulers.compaction_of_load为false来关闭这个功能.
另外一个选项, utilization balancing, 为了支持负载平衡, 默认是关闭的. 如果打开了这个选项, Erlang虚拟机则努力在不同调度器之间平衡调度器的利用. 如果不考虑每个调度器没有任务可调度的频度的话, 可以打开这个设置, erlang.schedulers.utilization_balancing 设为true(老版本里面通过设置+scl false) 另外一个选项, utilization balancing, 为了支持负载平衡, 默认是关闭的. 如果打开了这个选项, Erlang虚拟机则努力在不同调度器之间平衡调度器的利用. 如果不考虑每个调度器没有任务可调度的频度的话, 可以打开这个设置, erlang.schedulers.utilization_balancing 设为true(老版本里面通过设置+scl false)
在任何时候, 只可以是使用两个功能中的一个. 如果同时设置这两个选项为false的话, Riak 会默认使用集中负载选项.如果同时设置为true, Riak会使用那个在配置文件riak.conf中最先出现的那个.(如果是旧版本的话,配置文件会是vm.args) 在任何时候, 只可以是使用两个功能中的一个. 如果同时设置这两个选项为false的话, Riak 会默认使用集中负载选项.如果同时设置为true, Riak会使用那个在配置文件riak.conf中最先出现的那个.(如果是旧版本的话,配置文件会是vm.args)
##### Port Settings ##### Port Settings
Riak 使用epmd, Erlang 端口映射Daemon来进行大多数的节点间的通信. 在这个系统里, 集群里的其他节点使用由nodename参数(或者是name in vm.args)来作为节点ID. 比如, riak@10.9.8.7. 在每个节点上, daemon把这些节点ID解析成一个TCP的端口. 用户可以指定一个端口范围给Riak节点来监听使用,同时也可以知道最大数量的并ports/sockets.
Port Range
默认情况下 , epmd绑定到TCP端口4369上并且侦听通配符接口. epmd 默认使用一个不能预测的端口作为节点间的通信, 通过绑定到端口0上, 意味着会使用第一个可用的端口. 这样就使得防火墙非常难配置.
为了是防火墙配置简化, 用户可以指导Erlang虚拟机使用一个有限范围的端口或者单一端口. 这个最小和最大值可以设置在参数erlang.distribution.port_minimum和erlang.distribution.port_maximum里面. 比如, 下面的值被设为3000和5000.
riak.conf
app.config
erlang.distribution.port_range.minimum = 3000
erlang.distribution.port_range.maximum = 5000
用户可以设置Erlang虚拟机使用一个单一端口, 如果只设置了最小值没有设置最大值,则表示使用单一端口. 比如, 下面设置使用单一端口5000.
riak.conf
app.config
erlang.distribution.port_range.minimum = 5000
如果最小端口没有设置, Erlang虚拟机将会在随机的高编号端口上侦听.
Riak 使用epmd, Erlang 端口映射Daemon来进行大多数的节点间的通信. 在这个系统里, 集群里的其他节点使用由nodename参数(或者是name in vm.args)来作为节点ID. 比如,
riak@10.9.8.7. 在每个节点上, daemon把这些节点ID解析成一个TCP的端口. 用户可以指定一个端口范围给Riak节点来监听使用,同时也可以知道最大数量的并ports/sockets. Port Range 默认情况下 ,
epmd绑定到TCP端口4369上并且侦听通配符接口. epmd 默认使用一个不能预测的端口作为节点间的通信, 通过绑定到端口0上, 意味着会使用第一个可用的端口. 这样就使得防火墙非常难配置. 为了是防火墙配置简化,
用户可以指导Erlang虚拟机使用一个有限范围的端口或者单一端口. 这个最小和最大值可以设置在参数erlang.distribution.port_minimum和erlang.distribution.port_maximum里面.
比如, 下面的值被设为3000和5000. riak.conf app.config erlang.distribution.port_range.minimum = 3000
erlang.distribution.port_range.maximum = 5000 用户可以设置Erlang虚拟机使用一个单一端口, 如果只设置了最小值没有设置最大值,则表示使用单一端口. 比如, 下面设置使用单一端口5000.
riak.conf app.config erlang.distribution.port_range.minimum = 5000 如果最小端口没有设置, Erlang虚拟机将会在随机的高编号端口上侦听.
##### Maximum Ports ##### Maximum Ports
用户可以通过设置参数erlang.max_ports来指定Erlang虚拟机可以使用的最大并发的 ports/sockets数量, 范围从1024到134217727. 默认值是65536. 在vm.args里面对应的参数是+Q 或者-env ERL_MAX_PORTS.
Asynchronous Thread Pool
如果Erlang虚拟机支持线程可用, 用户可以为Erlang虚拟机设置异步线程池的线程数量, 使用参数erlang.async_threads(+A in vm.args). 线程数量范围从0至1024, 默认值是64,下面的例子是设置成600的情况.
riak.conf
vm.args
erlang.async_threads = 600
用户可以通过设置参数erlang.max_ports来指定Erlang虚拟机可以使用的最大并发的 ports/sockets数量, 范围从1024到134217727. 默认值是65536. 在vm.args里面对应的参数是+Q
或者-env ERL_MAX_PORTS. Asynchronous Thread Pool 如果Erlang虚拟机支持线程可用, 用户可以为Erlang虚拟机设置异步线程池的线程数量, 使用参数erlang.async_threads(
+A in vm.args). 线程数量范围从0至1024, 默认值是64,下面的例子是设置成600的情况. riak.conf vm.args erlang.async_threads = 600
##### Stack Size
除了可以指定异步线程的数量之外, 用户还可以为每个异步线程指定stack size. 参数是erlang.async_threads.stack_size, 对应到Erlang的+a参数. 用户可以在Riak中为这个参数指定size以KB,
MB,GB 为单位, 有效的范围值是16至8192个字, 在32位的系统上就是64至32768字节. 该参数没有默认值, 我们建议设置为16K words, 对应为64 KB在32位系统上.
我们建议这么小一个值是考虑到异步线程数量可能会很大. 注:The 64 KB default is enough for drivers delivered with Erlang/OTP but might not be large
enough to accommodate drivers that use the driver_async()functionality, documented here. We recommend setting higher
values with caution, always keeping the number of available threads in mind. Kernel Polling 如果系统支持, 用户可以在Erlang中利用内核轮询.
内核轮询可以在使用很多文件描述符的时候提高性能. 在使用中的文件描述符越多, 内核轮询发挥的作用就越大. 该选择在Riak的Erlang虚拟机中是默认打开的, 该参数对应到Erlang虚拟机中的+K参数
##### Stack Size
除了可以指定异步线程的数量之外, 用户还可以为每个异步线程指定stack size. 参数是erlang.async_threads.stack_size, 对应到Erlang的+a参数. 用户可以在Riak中为这个参数指定size以KB, MB,GB 为单位, 有效的范围值是16至8192个字, 在32位的系统上就是64至32768字节. 该参数没有默认值, 我们建议设置为16K words, 对应为64 KB在32位系统上. 我们建议这么小一个值是考虑到异步线程数量可能会很大.
注:The 64 KB default is enough for drivers delivered with Erlang/OTP but might not be large enough to accommodate drivers that use the driver_async()functionality, documented here. We recommend setting higher values with caution, always keeping the number of available threads in mind.
Kernel Polling
如果系统支持, 用户可以在Erlang中利用内核轮询. 内核轮询可以在使用很多文件描述符的时候提高性能. 在使用中的文件描述符越多, 内核轮询发挥的作用就越大. 该选择在Riak的Erlang虚拟机中是默认打开的, 该参数对应到Erlang虚拟机中的+K参数
##### Warning Messages
##### Warning Messages
Erlang虚拟机的error_logger 是一个事件管理器, 从Erlang运行时系统注册错误, 告警和信息事件. 默认情况下, error_logger的信息事件被映射为告警,但是用户可以设置映射成错误或者信息. 该设置为参数erlang.W, 可以设置的值为w(warning), errors 或者i(info reports).
Erlang虚拟机的error_logger 是一个事件管理器, 从Erlang运行时系统注册错误, 告警和信息事件. 默认情况下, error_logger的信息事件被映射为告警,但是用户可以设置映射成错误或者信息.
该设置为参数erlang.W, 可以设置的值为w(warning), errors 或者i(info reports).
##### Process Limit
##### Process Limit
参数erlang.process_limit可以用来设置系统同时存在的最大进程数量(对应到Erlang的+P参数), 有效范围从1024至134217727. 默认值是256000. 参数erlang.process_limit可以用来设置系统同时存在的最大进程数量(对应到Erlang的+P参数), 有效范围从1024至134217727. 默认值是256000.
##### Distribution Buffer
用户可以通过参数erlang.distribution_buffer_size设置Erlang虚拟机的distribution buffer busy limit(对应到Erlang的+zdbbl参数). 修改这个参数对那些有许多busy dist port事件的节点可能会有帮助, 默认值是32MB, 最大值是2097151KB. 增大这个参数可以允许进程缓存更多的待发消息, 当缓存满的时候,发送线程被挂起直到缓存减小到设定值. 所以, 更大的缓存有助于降低延迟以及增加吞吐量,代价就是使用了更多的RAM. 用户需要根据机器的RAM资源来考虑设定这个值.
##### Distribution Buffer
用户可以通过参数erlang.distribution_buffer_size设置Erlang虚拟机的distribution buffer busy limit(对应到Erlang的+zdbbl参数). 修改这个参数对那些有许多busy
dist port事件的节点可能会有帮助, 默认值是32MB, 最大值是2097151KB. 增大这个参数可以允许进程缓存更多的待发消息, 当缓存满的时候,发送线程被挂起直到缓存减小到设定值. 所以,
更大的缓存有助于降低延迟以及增加吞吐量,代价就是使用了更多的RAM. 用户需要根据机器的RAM资源来考虑设定这个值.
##### Erlang Built-in Storage ##### Erlang Built-in Storage
Erlang使用一个内置的数据库,ets(Erlang Term Storage)用来快速访问内存(constant access time rather than logarithmic access time). erts 表的最大数量设置在参数erlang.max_erts_tables里面, 默认值是256000,这个值要大于Erlang虚拟机自身的默认值1400(对应到vm.args 的参数e). 更大的erlang.max_erts_tables值可以提供更快的数据访问,代价是消耗更高的内存.
##### Crash Dumps
默认情况下, Riak 的Erlang crash dumps文件是存放在位置./log/erl_crash.dump. 用户可以通过设置参数erlang.crash_dump来更改存放位置. 该参数对应到Erlang虚拟机的ERL_CRASH_DUMP环境变量.
Erlang使用一个内置的数据库,ets(Erlang Term Storage)用来快速访问内存(constant access time rather than logarithmic access time). erts
表的最大数量设置在参数erlang.max_erts_tables里面, 默认值是256000,这个值要大于Erlang虚拟机自身的默认值1400(对应到vm.args 的参数e).
更大的erlang.max_erts_tables值可以提供更快的数据访问,代价是消耗更高的内存.
##### Net Kernel Tick Time
网络内核是Erlang的一个系统进程, 提供了不同的网络监视形式. 在一个Riak集群里面, 网络内核的功能之一就是去周期性的检测节点存活. Tick time就是这个检查频度, 可以通过erlang.distribution.net_ticktime设置,单位是秒. 该参数对应到vm.args里面的参数-kernal net_ticktime.
##### Crash Dumps
默认情况下, Riak 的Erlang crash dumps文件是存放在位置./log/erl_crash.dump. 用户可以通过设置参数erlang.crash_dump来更改存放位置.
该参数对应到Erlang虚拟机的ERL_CRASH_DUMP环境变量.
##### Net Kernel Tick Time
网络内核是Erlang的一个系统进程, 提供了不同的网络监视形式. 在一个Riak集群里面, 网络内核的功能之一就是去周期性的检测节点存活. Tick time就是这个检查频度,
可以通过erlang.distribution.net_ticktime设置,单位是秒. 该参数对应到vm.args里面的参数-kernal net_ticktime.
##### Shutdown Time
用户可以设定Erlang虚拟机的关闭时间, 该设置参数为erlang.shutdown_time,默认是10秒, 一旦10秒过了, 所有存在的进程就会被杀掉. 减少关闭时间在某些情景下可能是有帮助的,
比如说在测试的时候需要频繁的启停Riak集群. 在vm.args里参数是shutdown_time, 单位是毫秒.
##### Shutdown Time
用户可以设定Erlang虚拟机的关闭时间, 该设置参数为erlang.shutdown_time,默认是10秒, 一旦10秒过了, 所有存在的进程就会被杀掉. 减少关闭时间在某些情景下可能是有帮助的, 比如说在测试的时候需要频繁的启停Riak集群. 在vm.args里参数是shutdown_time, 单位是毫秒.
gen_tcp 编程接口 gen_tcp 编程接口
#### listen(Port, Options) -> {ok, ListenSocket} | {error, Reason} #### listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}
Types Types
Port = inet:port_number() Port = inet:port_number()
Options = [listen_option()] Options = [listen_option()]
@ -287,8 +292,9 @@ gen_tcp 编程接口
{Rand, _RandSeed} = random:uniform_s(9999, erlang:now()), {Rand, _RandSeed} = random:uniform_s(9999, erlang:now()),
Port = 40000 + Rand, Port = 40000 + Rand,
gen_tcp:listen(Port, [binary, {packet, 0}, {active, false}]). gen_tcp:listen(Port, [binary, {packet, 0}, {active, false}]).
#### accept(ListenSocket) -> {ok, Socket} | {error, Reason} accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason} #### accept(ListenSocket) -> {ok, Socket} | {error, Reason} accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}
Types Types
ListenSocket = socket() Returned by listen/2. ListenSocket = socket() Returned by listen/2.
Timeout = timeout() Socket = socket() Reason = closed | timeout | system_limit | inet:posix() Timeout = timeout() Socket = socket() Reason = closed | timeout | system_limit | inet:posix()
@ -327,9 +333,11 @@ gen_tcp 编程接口
_ -> _ ->
socket_listen_fail socket_listen_fail
end. end.
#### connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} #### connect(Address, Port, Options) -> {ok, Socket} | {error, Reason}
#### connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason} #### connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason}
Types Types
Address = inet:socket_address() | Address = inet:socket_address() |
inet:hostname() Port = inet:port_number() inet:hostname() Port = inet:port_number()
@ -379,18 +387,20 @@ gen_tcp 编程接口
注意::: 注意:::
请记住,如果底层OS connect()的调用返回超时,调用gen_tcp:连接也将返回超时(即{错误,ETIMEDOUT} ),即使较大的超时指定。 请记住,如果底层OS connect()的调用返回超时,调用gen_tcp:连接也将返回超时(即{错误,ETIMEDOUT} ),即使较大的超时指定。
指定要连接的选项的默认值会受到内核配置参数 inet_default_connect_options的影响。有关详细信息,请参见 inet(3)。 指定要连接的选项的默认值会受到内核配置参数 inet_default_connect_options的影响。有关详细信息,请参见 inet(3)。
#### gen_tcp:close/1 #### gen_tcp:close/1
Types Types
Socket = socket() Socket = socket()
关闭一个 TCP 套接字 关闭一个 TCP 套接字
请注意,在大多数TCP实现中,执行关闭操作并不能保证在远程端检测到关闭之前,已发送的任何数据都会传递给接收方。如果要保证将数据传递给收件人,可以通过两种常用方法来实现。 请注意,在大多数TCP实现中,执行关闭操作并不能保证在远程端检测到关闭之前,已发送的任何数据都会传递给接收方。如果要保证将数据传递给收件人,可以通过两种常用方法来实现。
使用gen_tcp:shutdown(Sock,write)发出信号,表明不再发送任何数据,并等待套接字的读取端关闭。 使用gen_tcp:shutdown(Sock,write)发出信号,表明不再发送任何数据,并等待套接字的读取端关闭。
使用套接字选项{packet,N}(或类似的选项)可以使接收器在知道已接收到所有数据时关闭连接。 使用套接字选项{packet,N}(或类似的选项)可以使接收器在知道已接收到所有数据时关闭连接。
#### recv(Socket, Length) -> {ok, Packet} | {error, Reason} #### recv(Socket, Length) -> {ok, Packet} | {error, Reason}
#### recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason} #### recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason}
Types Types
Socket = socket() Socket = socket()
Length = integer() >= 0 Length = integer() >= 0
@ -432,6 +442,7 @@ gen_tcp 编程接口
end. end.
#### send(Socket, Packet) -> ok | {error, Reason} #### send(Socket, Packet) -> ok | {error, Reason}
Types Types
Socket = socket() Socket = socket()
Packet = iodata() Packet = iodata()
@ -442,6 +453,7 @@ gen_tcp 编程接口
在一个套接字 Socket 发送一个数据包。 在一个套接字 Socket 发送一个数据包。
#### shutdown(Socket, How) -> ok | {error, Reason} #### shutdown(Socket, How) -> ok | {error, Reason}
Types Types
Socket = socket() Socket = socket()
How = read | write | read_write How = read | write | read_write
@ -457,9 +469,9 @@ gen_tcp 编程接口
如果遇到任何错误,则关闭套接字,并在下一个recv / 2或 send / 2上返回 {error,closed}。 如果遇到任何错误,则关闭套接字,并在下一个recv / 2或 send / 2上返回 {error,closed}。
如果对等方在写端执行了关闭操作,则选项{exit_on_close,false}很有用。 如果对等方在写端执行了关闭操作,则选项{exit_on_close,false}很有用。
#### gen_tcp:controlling_process/2 #### gen_tcp:controlling_process/2
改变一个套接字的控制进程 改变一个套接字的控制进程
将新的控制过程Pid分配给 Socket。控制过程是从套接字接收消息的过程。 将新的控制过程Pid分配给 Socket。控制过程是从套接字接收消息的过程。
@ -470,8 +482,9 @@ gen_tcp 编程接口
如果套接字设置为活动模式,则此功能会将呼叫者邮箱中的所有消息传送到新的控制进程。 如果套接字设置为活动模式,则此功能会将呼叫者邮箱中的所有消息传送到新的控制进程。
如果在传输过程中有任何其他进程正在与套接字交互,则传输可能无法正常进行,并且消息可能会保留在呼叫者的邮箱中。 如果在传输过程中有任何其他进程正在与套接字交互,则传输可能无法正常进行,并且消息可能会保留在呼叫者的邮箱中。
例如,在传输完成之前更改套接字活动模式可能会导致此情况 例如,在传输完成之前更改套接字活动模式可能会导致此情况
#### 套接字选项 #### 套接字选项
{active, true | false | once | -32768..32767} | {active, true | false | once | -32768..32767} |
如果值为true,这是默认值,则将从套接字接收的所有内容作为消息发送到接收进程。 如果值为true,这是默认值,则将从套接字接收的所有内容作为消息发送到接收进程。
如果值为false(被动模式),则该进程必须通过调用gen_tcp:recv / 2,3, gen_udp:recv / 2,3或gen_sctp:recv / 1,2来显式接收传入的数据 (取决于套接字的类型) )。 如果值为false(被动模式),则该进程必须通过调用gen_tcp:recv / 2,3, gen_udp:recv / 2,3或gen_sctp:recv / 1,2来显式接收传入的数据 (取决于套接字的类型) )。
@ -627,38 +640,18 @@ gen_tcp 编程接口
{recvtos, boolean()} | {recvtos, boolean()} |
{recvtclass, boolean()} | {recvtclass, boolean()} |
{recvttl, boolean()} | {recvttl, boolean()} |
option_name() =
active | buffer | delay_send | deliver | dontroute |
exit_on_close | header | high_msgq_watermark |
high_watermark | keepalive | linger | low_msgq_watermark |
low_watermark | mode | nodelay | packet | packet_size |
pktoptions | priority |
{raw,Protocol :: integer() >= 0, OptionNum :: integer() >= 0, ValueSpec ::(ValueSize :: integer() >= 0) | (ValueBin :: binary())} |
recbuf | reuseaddr | send_timeout | send_timeout_close |
show_econnreset | sndbuf | tos | tclass | ttl | recvtos |
recvtclass | recvttl | pktoptions | ipv6_v6only
connect_option() =
{ip, inet:socket_address()} |
{fd, Fd :: integer() >= 0} |
{ifaddr, inet:socket_address()} |
inet:address_family() |
{port, inet:port_number()} |
{tcp_module, module()} |
{netns, file:filename_all()} |
{bind_to_device, binary()} |
option()
listen_option() =
{ip, inet:socket_address()} |
{fd, Fd :: integer() >= 0} |
{ifaddr, inet:socket_address()} |
inet:address_family() |
{port, inet:port_number()} |
{backlog, B :: integer() >= 0} |
{tcp_module, module()} |
{netns, file:filename_all()} |
{bind_to_device, binary()} |
option()
socket()
As returned by accept/1,2 and connect/3,4.
option_name() = active | buffer | delay_send | deliver | dontroute | exit_on_close | header | high_msgq_watermark |
high_watermark | keepalive | linger | low_msgq_watermark | low_watermark | mode | nodelay | packet | packet_size |
pktoptions | priority | {raw,Protocol :: integer() >= 0, OptionNum :: integer() >= 0, ValueSpec ::(ValueSize ::
integer() >= 0) | (ValueBin :: binary())} | recbuf | reuseaddr | send_timeout | send_timeout_close | show_econnreset |
sndbuf | tos | tclass | ttl | recvtos | recvtclass | recvttl | pktoptions | ipv6_v6only
connect_option() = {ip, inet:socket_address()} | {fd, Fd :: integer() >= 0} | {ifaddr, inet:socket_address()} | inet:
address_family() | {port, inet:port_number()} | {tcp_module, module()} | {netns, file:filename_all()} | {bind_to_device,
binary()} | option()
listen_option() = {ip, inet:socket_address()} | {fd, Fd :: integer() >= 0} | {ifaddr, inet:socket_address()} | inet:
address_family() | {port, inet:port_number()} | {backlog, B :: integer() >= 0} | {tcp_module, module()} | {netns, file:
filename_all()} | {bind_to_device, binary()} | option()
socket()
As returned by accept/1,2 and connect/3,4.

+ 11
- 11
src/misc/ntCidr.erl View File

@ -10,7 +10,7 @@
, is_ipv6/1 , is_ipv6/1
]). ]).
-export_type([ cidr_string/0
-export_type([cidr_string/0
, cidr/0 , cidr/0
]). ]).
@ -25,7 +25,7 @@ parse(S) ->
-spec(parse(string(), boolean()) -> cidr()). -spec(parse(string(), boolean()) -> cidr()).
parse(S, Adjust) -> parse(S, Adjust) ->
case string:tokens(S, "/") of case string:tokens(S, "/") of
[AddrStr] -> parse_addr(AddrStr);
[AddrStr] -> parse_addr(AddrStr);
[AddrStr, LenStr] -> parse_cidr(AddrStr, LenStr, Adjust) [AddrStr, LenStr] -> parse_cidr(AddrStr, LenStr, Adjust)
end. end.
@ -106,21 +106,21 @@ end_mask({_, _, _, _}, Len) when 0 =< Len, Len =< 32 ->
Len == 32 -> {0, 0, 0, 0}; Len == 32 -> {0, 0, 0, 0};
Len >= 24 -> {0, 0, 0, bmask(Len, 8)}; Len >= 24 -> {0, 0, 0, bmask(Len, 8)};
Len >= 16 -> {0, 0, bmask(Len, 8), 16#FF}; Len >= 16 -> {0, 0, bmask(Len, 8), 16#FF};
Len >= 8 -> {0, bmask(Len, 8), 16#FF, 16#FF};
Len >= 0 -> {bmask(Len, 8), 16#FF, 16#FF, 16#FF}
Len >= 8 -> {0, bmask(Len, 8), 16#FF, 16#FF};
Len >= 0 -> {bmask(Len, 8), 16#FF, 16#FF, 16#FF}
end; end;
end_mask({_, _, _, _, _, _, _, _}, Len) when 0 =< Len, Len =< 128 -> end_mask({_, _, _, _, _, _, _, _}, Len) when 0 =< Len, Len =< 128 ->
if if
Len == 128 -> {0, 0, 0, 0, 0, 0, 0, 0}; Len == 128 -> {0, 0, 0, 0, 0, 0, 0, 0};
Len >= 112 -> {0, 0, 0, 0, 0, 0, 0, bmask(Len, 16)}; Len >= 112 -> {0, 0, 0, 0, 0, 0, 0, bmask(Len, 16)};
Len >= 96 -> {0, 0, 0, 0, 0, 0, bmask(Len, 16), 16#FFFF};
Len >= 80 -> {0, 0, 0, 0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF};
Len >= 64 -> {0, 0, 0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 49 -> {0, 0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 32 -> {0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 16 -> {0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 0 -> {bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF}
Len >= 96 -> {0, 0, 0, 0, 0, 0, bmask(Len, 16), 16#FFFF};
Len >= 80 -> {0, 0, 0, 0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF};
Len >= 64 -> {0, 0, 0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 49 -> {0, 0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 32 -> {0, 0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 16 -> {0, bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF};
Len >= 0 -> {bmask(Len, 16), 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF, 16#FFFF}
end. end.
bmask(I, 8) when 0 =< I, I =< 32 -> bmask(I, 8) when 0 =< I, I =< 32 ->

+ 20
- 20
src/misc/ntCom.erl View File

@ -51,40 +51,40 @@ parseAddr(Port) ->
isIpv4OrIpv6({A, B, C, D}) -> isIpv4OrIpv6({A, B, C, D}) ->
A >= 0 andalso A =< 255 andalso A >= 0 andalso A =< 255 andalso
B >= 0 andalso B =< 255 andalso
C >= 0 andalso C =< 255 andalso
D >= 0 andalso D =< 255;
B >= 0 andalso B =< 255 andalso
C >= 0 andalso C =< 255 andalso
D >= 0 andalso D =< 255;
isIpv4OrIpv6({A, B, C, D, E, F, G, H}) -> isIpv4OrIpv6({A, B, C, D, E, F, G, H}) ->
A >= 0 andalso A =< 65535 andalso A >= 0 andalso A =< 65535 andalso
B >= 0 andalso B =< 65535 andalso
C >= 0 andalso C =< 65535 andalso
D >= 0 andalso D =< 65535 andalso
E >= 0 andalso E =< 65535 andalso
F >= 0 andalso F =< 65535 andalso
G >= 0 andalso G =< 65535 andalso
H >= 0 andalso H =< 65535;
B >= 0 andalso B =< 65535 andalso
C >= 0 andalso C =< 65535 andalso
D >= 0 andalso D =< 65535 andalso
E >= 0 andalso E =< 65535 andalso
F >= 0 andalso F =< 65535 andalso
G >= 0 andalso G =< 65535 andalso
H >= 0 andalso H =< 65535;
isIpv4OrIpv6(_) -> isIpv4OrIpv6(_) ->
false. false.
%% @doc Return true if the value is an ipv4 address %% @doc Return true if the value is an ipv4 address
isIpv4({A, B, C, D}) -> isIpv4({A, B, C, D}) ->
A >= 0 andalso A =< 255 andalso A >= 0 andalso A =< 255 andalso
B >= 0 andalso B =< 255 andalso
C >= 0 andalso C =< 255 andalso
D >= 0 andalso D =< 255;
B >= 0 andalso B =< 255 andalso
C >= 0 andalso C =< 255 andalso
D >= 0 andalso D =< 255;
isIpv4(_) -> isIpv4(_) ->
false. false.
%% @doc Return true if the value is an ipv6 address %% @doc Return true if the value is an ipv6 address
isIpv6({A, B, C, D, E, F, G, H}) -> isIpv6({A, B, C, D, E, F, G, H}) ->
A >= 0 andalso A =< 65535 andalso A >= 0 andalso A =< 65535 andalso
B >= 0 andalso B =< 65535 andalso
C >= 0 andalso C =< 65535 andalso
D >= 0 andalso D =< 65535 andalso
E >= 0 andalso E =< 65535 andalso
F >= 0 andalso F =< 65535 andalso
G >= 0 andalso G =< 65535 andalso
H >= 0 andalso H =< 65535;
B >= 0 andalso B =< 65535 andalso
C >= 0 andalso C =< 65535 andalso
D >= 0 andalso D =< 65535 andalso
E >= 0 andalso E =< 65535 andalso
F >= 0 andalso F =< 65535 andalso
G >= 0 andalso G =< 65535 andalso
H >= 0 andalso H =< 65535;
isIpv6(_) -> isIpv6(_) ->
false. false.

+ 1
- 1
src/misc/ntTBucket.erl View File

@ -47,7 +47,7 @@ check(Consume, TokenBucket) ->
check(Consume, Now, #tBucket{rate = Rate, tokens = Tokens, lastTime = LastTime, bucketSize = BucketSize} = TokenBucket) -> check(Consume, Now, #tBucket{rate = Rate, tokens = Tokens, lastTime = LastTime, bucketSize = BucketSize} = TokenBucket) ->
AvailableToken = erlang:min(BucketSize, Tokens + (Rate * (Now - LastTime)) div 1000), AvailableToken = erlang:min(BucketSize, Tokens + (Rate * (Now - LastTime)) div 1000),
case AvailableToken >= Consume of case AvailableToken >= Consume of
true ->
true ->
%% Tokens available %% Tokens available
{0, TokenBucket#tBucket{tokens = AvailableToken - Consume, lastTime = Now}}; {0, TokenBucket#tBucket{tokens = AvailableToken - Consume, lastTime = Now}};
false -> false ->

+ 1
- 1
src/proxyPt/ntPptAcceptorSup.erl View File

@ -10,7 +10,7 @@
init/1 init/1
]). ]).
-spec(start_link(SupName :: atom(), SslOpts :: list(), SslHSTet :: timeout(), ProxyPt :: boolean(), ProxyPtTet :: timeout()) -> {ok, pid()}).
-spec(start_link(SupName :: atom(), SslOpts :: list(), SslHSTet :: timeout(), ProxyPt :: boolean(), ProxyPtTet :: timeout()) -> {ok, pid()}).
start_link(SupName, SslOpts, SslHSTet, ProxyPt, ProxyPtTet) -> start_link(SupName, SslOpts, SslHSTet, ProxyPt, ProxyPtTet) ->
supervisor:start_link({local, SupName}, ?MODULE, {SslOpts, SslHSTet, ProxyPt, ProxyPtTet}). supervisor:start_link({local, SupName}, ?MODULE, {SslOpts, SslHSTet, ProxyPt, ProxyPtTet}).

+ 2
- 2
src/proxyPt/nt_proxy_protocol.erl View File

@ -103,7 +103,7 @@ parse_v1(Sock, ProxyInfo, ProxySock) ->
DstPort = list_to_integer(binary_to_list(DstPortBin)), DstPort = list_to_integer(binary_to_list(DstPortBin)),
{ok, Sock, ProxySock#proxy_socket{src_addr = SrcAddr, dst_addr = DstAddr, src_port = SrcPort, dst_port = DstPort}}. {ok, Sock, ProxySock#proxy_socket{src_addr = SrcAddr, dst_addr = DstAddr, src_port = SrcPort, dst_port = DstPort}}.
parse_v2(?LOCAL, _Trans, _ProxyInfo, ProxySocket , Sock) ->
parse_v2(?LOCAL, _Trans, _ProxyInfo, ProxySocket, Sock) ->
{ok, Sock, ProxySocket}; {ok, Sock, ProxySocket};
parse_v2(?PROXY, ?STREAM, ProxyInfo, ProxySock = #proxy_socket{inet = inet4}, Sock) -> parse_v2(?PROXY, ?STREAM, ProxyInfo, ProxySock = #proxy_socket{inet = inet4}, Sock) ->
<<A:8, B:8, C:8, D:8, W:8, X:8, Y:8, Z:8, SrcPort:16, DstPort:16, AdditionalBytes/binary>> = ProxyInfo, <<A:8, B:8, C:8, D:8, W:8, X:8, Y:8, Z:8, SrcPort:16, DstPort:16, AdditionalBytes/binary>> = ProxyInfo,
@ -111,7 +111,7 @@ parse_v2(?PROXY, ?STREAM, ProxyInfo, ProxySock = #proxy_socket{inet = inet4}, So
parse_v2(?PROXY, ?STREAM, ProxyInfo, ProxySock = #proxy_socket{inet = inet6}, Sock) -> parse_v2(?PROXY, ?STREAM, ProxyInfo, ProxySock = #proxy_socket{inet = inet6}, Sock) ->
<<A:16, B:16, C:16, D:16, E:16, F:16, G:16, H:16, R:16, S:16, T:16, U:16, V:16, W:16, X:16, Y:16, SrcPort:16, DstPort:16, AdditionalBytes/binary>> = ProxyInfo, <<A:16, B:16, C:16, D:16, E:16, F:16, G:16, H:16, R:16, S:16, T:16, U:16, V:16, W:16, X:16, Y:16, SrcPort:16, DstPort:16, AdditionalBytes/binary>> = ProxyInfo,
parse_pp2_additional(AdditionalBytes, ProxySock#proxy_socket{src_addr = {A, B, C, D, E, F, G, H}, src_port = SrcPort, dst_addr = {R, S, T, U, V, W, X, Y}, dst_port = DstPort}, Sock); parse_pp2_additional(AdditionalBytes, ProxySock#proxy_socket{src_addr = {A, B, C, D, E, F, G, H}, src_port = SrcPort, dst_addr = {R, S, T, U, V, W, X, Y}, dst_port = DstPort}, Sock);
parse_v2(_, _, _,_, _) ->
parse_v2(_, _, _, _, _) ->
{error, unsupported_proto_v2}. {error, unsupported_proto_v2}.
parse_pp2_additional(<<>>, ProxySock, Sock) -> parse_pp2_additional(<<>>, ProxySock, Sock) ->

+ 1
- 1
src/tcp/ntTcpAcceptor.erl View File

@ -82,7 +82,7 @@ init({LSock, ConMod}) ->
case prim_inet:async_accept(LSock, -1) of case prim_inet:async_accept(LSock, -1) of
{ok, Ref} -> {ok, Ref} ->
{ok, SockMod} = inet_db:lookup_socket(LSock), {ok, SockMod} = inet_db:lookup_socket(LSock),
{ok, #state{lSock = LSock, ref = Ref, conMod = ConMod, sockMod = SockMod}};
{ok, #state{lSock = LSock, ref = Ref, conMod = ConMod, sockMod = SockMod}};
{error, Reason} -> {error, Reason} ->
?ntErr("init prim_inet:async_accept error ~p~n", [Reason]), ?ntErr("init prim_inet:async_accept error ~p~n", [Reason]),
{stop, Reason} {stop, Reason}

+ 6
- 6
src/test/utTcpAFSrv.erl View File

@ -37,7 +37,7 @@ handle_call(_Request, _From, State) ->
handle_cast(_Msg, State) -> handle_cast(_Msg, State) ->
io:format("handle_cast for______ ~p~n", [_Msg]), io:format("handle_cast for______ ~p~n", [_Msg]),
{noreply, State}.
{noreply, State}.
handle_info({inet_async, Sock, _Ref, {ok, Data}}, State = #state{socket = _Sock}) -> handle_info({inet_async, Sock, _Ref, {ok, Data}}, State = #state{socket = _Sock}) ->
{ok, Peername} = inet:peername(Sock), {ok, Peername} = inet:peername(Sock),
@ -55,8 +55,8 @@ handle_info({inet_reply, _Sock, ok}, State) ->
{noreply, State}; {noreply, State};
handle_info({inet_reply, _Sock, {error, Reason}}, State) -> handle_info({inet_reply, _Sock, {error, Reason}}, State) ->
io:format("Shutdown for ~p~n", [Reason]),
shutdown(Reason, State);
io:format("Shutdown for ~p~n", [Reason]),
shutdown(Reason, State);
handle_info({miSockReady, Sock}, State) -> handle_info({miSockReady, Sock}, State) ->
prim_inet:async_recv(Sock, 0, -1), prim_inet:async_recv(Sock, 0, -1),
@ -65,14 +65,14 @@ handle_info({miSockReady, Sock}, State) ->
handle_info(_Info, State) -> handle_info(_Info, State) ->
io:format("handle_info for______ ~p~n", [_Info]), io:format("handle_info for______ ~p~n", [_Info]),
{noreply, State}.
{noreply, State}.
terminate(_Reason, #state{socket = Sock}) -> terminate(_Reason, #state{socket = Sock}) ->
catch gen_tcp:close(Sock). catch gen_tcp:close(Sock).
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}.
{ok, State}.
shutdown(Reason, State) -> shutdown(Reason, State) ->
{stop, {shutdown, Reason}, State}.
{stop, {shutdown, Reason}, State}.

+ 25
- 25
src/test/utTcpCli.erl View File

@ -5,36 +5,36 @@
-define(TCP_OPTIONS, [binary, {packet, 0}, {active, true}]). -define(TCP_OPTIONS, [binary, {packet, 0}, {active, true}]).
start(0, _Num, _Host, _Port) -> start(0, _Num, _Host, _Port) ->
ok;
ok;
start(Cnt, Num, Host, Port) -> start(Cnt, Num, Host, Port) ->
spawn(?MODULE, connect, [Num, self(), Host, Port]),
start(Cnt - 1, Num, Host, Num).
spawn(?MODULE, connect, [Num, self(), Host, Port]),
start(Cnt - 1, Num, Host, Num).
connect(Num, Parent, Host, Port) -> connect(Num, Parent, Host, Port) ->
case gen_tcp:connect(Host, Port, ?TCP_OPTIONS, 6000) of
{ok, Sock} ->
Parent ! {connected, Sock},
loop(Num, Sock);
{error, Reason} ->
io:format("Client ~p connect error: ~p~n", [Num, Reason])
end.
case gen_tcp:connect(Host, Port, ?TCP_OPTIONS, 6000) of
{ok, Sock} ->
Parent ! {connected, Sock},
loop(Num, Sock);
{error, Reason} ->
io:format("Client ~p connect error: ~p~n", [Num, Reason])
end.
loop(Num, Sock) -> loop(Num, Sock) ->
% Timeout = 5000 + rand:uniform(5000),
receive
{tcp, Sock, Data} ->
io:format("Client ~w received: ~s~n", [Num, Data]),
loop(Num, Sock);
{tcp_closed, Sock} ->
io:format("Client ~w socket closed~n", [Num]);
{tcp_error, Sock, Reason} ->
io:format("Client ~w socket error: ~p~n", [Num, Reason]);
Other ->
io:format("Client ~w unexpected: ~p", [Num, Other])
after 0 ->
send(Num, Sock), loop(Num, Sock)
end.
% Timeout = 5000 + rand:uniform(5000),
receive
{tcp, Sock, Data} ->
io:format("Client ~w received: ~s~n", [Num, Data]),
loop(Num, Sock);
{tcp_closed, Sock} ->
io:format("Client ~w socket closed~n", [Num]);
{tcp_error, Sock, Reason} ->
io:format("Client ~w socket error: ~p~n", [Num, Reason]);
Other ->
io:format("Client ~w unexpected: ~p", [Num, Other])
after 0 ->
send(Num, Sock), loop(Num, Sock)
end.
send(N, Sock) -> send(N, Sock) ->
gen_tcp:send(Sock, [integer_to_list(N), ":", <<"Hello, eSockd!">>]).
gen_tcp:send(Sock, [integer_to_list(N), ":", <<"Hello, eSockd!">>]).

+ 25
- 25
src/test/utUdpCli.erl View File

@ -5,36 +5,36 @@
-define(UDP_OPTIONS, [binary, {active, true}]). -define(UDP_OPTIONS, [binary, {active, true}]).
start(0, _Num, _Host, _Port) -> start(0, _Num, _Host, _Port) ->
ok;
ok;
start(Cnt, Num, Host, Port) -> start(Cnt, Num, Host, Port) ->
spawn(?MODULE, connect, [Num, self(), Host, Port]),
start(Cnt - 1, Num, Host, Num).
spawn(?MODULE, connect, [Num, self(), Host, Port]),
start(Cnt - 1, Num, Host, Num).
connect(Num, Parent, Host, Port) -> connect(Num, Parent, Host, Port) ->
case gen_udp:open(0, ?UDP_OPTIONS) of
{ok, Sock} ->
Parent ! {connected, Sock},
loop(Num, Sock, Host, Port);
{error, Reason} ->
io:format("Client ~p connect error: ~p~n", [Num, Reason])
end.
case gen_udp:open(0, ?UDP_OPTIONS) of
{ok, Sock} ->
Parent ! {connected, Sock},
loop(Num, Sock, Host, Port);
{error, Reason} ->
io:format("Client ~p connect error: ~p~n", [Num, Reason])
end.
loop(Num, Sock, Host, Port) -> loop(Num, Sock, Host, Port) ->
% Timeout = 5000 + rand:uniform(5000),
receive
{udp, Sock, IP, InPortNo, Data} ->
io:format("Client ~w received: ~p ~p ~s~n", [Num, IP, InPortNo, Data]),
loop(Num -1 , Sock, Host, Port);
{udp, Sock, IP, InPortNo, AncData, Data} ->
io:format("Client ~w received: ~p ~p ~p ~s~n", [Num, IP, InPortNo, AncData, Data]),
loop(Num -1, Sock, Host, Port);
Other ->
io:format("Client ~w unexpected: ~p", [Num, Other])
after 5000 ->
send(Num, Sock, Host, Port), loop(Num-1 , Sock, Host, Port)
end.
% Timeout = 5000 + rand:uniform(5000),
receive
{udp, Sock, IP, InPortNo, Data} ->
io:format("Client ~w received: ~p ~p ~s~n", [Num, IP, InPortNo, Data]),
loop(Num - 1, Sock, Host, Port);
{udp, Sock, IP, InPortNo, AncData, Data} ->
io:format("Client ~w received: ~p ~p ~p ~s~n", [Num, IP, InPortNo, AncData, Data]),
loop(Num - 1, Sock, Host, Port);
Other ->
io:format("Client ~w unexpected: ~p", [Num, Other])
after 5000 ->
send(Num, Sock, Host, Port), loop(Num - 1, Sock, Host, Port)
end.
send(N, Sock, Host, Port) -> send(N, Sock, Host, Port) ->
io:format("fdsfsfs ~n"),
gen_udp:send(Sock, Host, Port, [integer_to_list(N), ":", <<"Hello, eSockd!">>]).
io:format("fdsfsfs ~n"),
gen_udp:send(Sock, Host, Port, [integer_to_list(N), ":", <<"Hello, eSockd!">>]).

Loading…
Cancel
Save