你如何使用Gun作为牛仔客户?

时间:2017-07-10 07:22:42

标签: erlang cowboy

我跟着Getting Started instructions找了牛仔,我已经让牛仔跑步并听8080端口了,当我在浏览器中输入Hello Erlang!时,我收到http://localhost:8080响应。现在,我如何使用Gun连接到Cowboy?

我读了Gun docs,并说它将#gn; Gun作为erlang.mk依赖"添加。所以我下载了erlang.mk:

~/erlang_programs/my_gun$ curl -O https://erlang.mk/erlang.mk

并在Erlang.mk User Guide之后,我创建了一个应用程序:

~/erlang_programs/my_gun$ gmake -f erlang.mk bootstrap

然后我添加了枪作为Makefile的依赖:

PROJECT = my_gun
PROJECT_DESCRIPTION = New project
PROJECT_VERSION = 0.1.0

DEPS = gun

include erlang.mk

然后我编译:

~/erlang_programs/my_gun$ gmake
gmake[1]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
 ERLC   cow_cookie.erl cow_date.erl cow_hpack.erl cow_http.erl cow_http2.erl cow_http_hd.erl cow_http_te.erl cow_mimetypes.erl cow_multipart.erl cow_qs.erl cow_spdy.erl cow_sse.erl cow_uri.erl cow_ws.erl
 APP    cowlib
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
 DEPEND ranch.d
 ERLC   ranch.erl ranch_acceptor.erl ranch_acceptors_sup.erl ranch_app.erl ranch_conns_sup.erl ranch_listener_sup.erl ranch_protocol.erl ranch_server.erl ranch_ssl.erl ranch_sup.erl ranch_tcp.erl ranch_transport.erl
 APP    ranch
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
 DEPEND gun.d
 ERLC   gun.erl gun_app.erl gun_content_handler.erl gun_data.erl gun_http.erl gun_http2.erl gun_spdy.erl gun_sse.erl gun_sup.erl gun_ws.erl gun_ws_handler.erl
 APP    gun
 GEN    rebar.config
gmake[1]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
 DEPEND my_gun.d
 ERLC   my_gun_app.erl my_gun_sup.erl
 APP    my_gun
 GEN    /Users/7stud/erlang_programs/my_gun/.erlang.mk/relx
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /Users/7stud/erlang_programs/my_gun/ebin
          /Users/7stud/erlang_programs/my_gun/deps
          /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang/lib
          /Users/7stud/erlang_programs/my_gun/apps
===> Resolved my_gun_release-1
===> rendering builtin_hook_status hook to "/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/bin/hooks/builtin/status"
===> Including Erts from /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang
===> release successfully created!
===> tarball /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/my_gun_release-1.tar.gz successfully created!

但是当我切换到erlang shell并尝试启动枪时,我收到一个错误:

~/erlang_programs/my_gun$ erl
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] 

Eshell V8.2  (abort with ^G)

1> application:ensure_all_started(gun).
{error,{gun,{"no such file or directory","gun.app"}}}

有人可以发布一个简单的示例,说明如何使用Gun(或任何其他支持websocket的http客户端)连接到Cowboy?

好的,我取得了一些进展。我删除了my_gun目录,重新创建了目录,重新下载了erlang.mk,并使用以下command创建了 一个版本

~/erlang_programs/my_gun$ gmake -f erlang.mk bootstrap-lib bootstrap-rel

然后我将枪依赖项添加到Makefile(如上所述)。然后我做了:

 ~/erlang_programs/my_gun$ gmake run

如果代码中没有错误,那么将启动erlang shell。在erlang shell中,我输入了以下代码(请参阅下面的tip以避免在shell中键入所有代码):

(my_gun@127.0.0.1)1> application:ensure_all_started(gun).
{ok,[]}

(my_gun@127.0.0.1)2> {ok, ConnPid} = gun:open("localhost", 8080).  

=PROGRESS REPORT==== 10-Jul-2017::05:21:58 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.366.0>},{mfa,{inet_gethost_native,init,[[]]}}]
{ok,<0.364.0>}

=PROGRESS REPORT==== 10-Jul-2017::05:21:58 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.365.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]

(my_gun@127.0.0.1)3> {ok, Protocol} = gun:await_up(ConnPid).
{ok,http}

(my_gun@127.0.0.1)4> gun:ws_upgrade(ConnPid, "/websocket").
#Ref<0.0.3.244>

(my_gun@127.0.0.1)5> receive                                          
(my_gun@127.0.0.1)5> {gun_ws_upgrade, ConnPid, ok, Headers} ->        
(my_gun@127.0.0.1)5> upgrade_success(ConnPid);
(my_gun@127.0.0.1)5> {gun_response, ConnPid, _, _, Status, Headers} ->
(my_gun@127.0.0.1)5> exit({ws_upgrade_failed, Status, Headers});
(my_gun@127.0.0.1)5> {gun_error, ConnPid, StreamRef, Reason} ->
(my_gun@127.0.0.1)5> exit({ws_upgrade_failed, Reason})
(my_gun@127.0.0.1)5> after 1000 ->
(my_gun@127.0.0.1)5> exit(timeout)
(my_gun@127.0.0.1)5> end.

=CRASH REPORT==== 10-Jul-2017::05:25:17 ===
  crasher:
    initial call: gun:proc_lib_hack/5
    pid: <0.364.0>
    registered_name: []
    exception exit: {{owner_gone,normal},
                     [{gun,loop,1,[{file,"src/gun.erl"},{line,706}]},
                      {gun,proc_lib_hack,5,[{file,"src/gun.erl"},{line,535}]},
                      {proc_lib,init_p_do_apply,3,
                                [{file,"proc_lib.erl"},{line,247}]}]}
      in function  gun:proc_lib_hack/5 (src/gun.erl, line 540)
    ancestors: [gun_sup,<0.343.0>]
    messages: []
    links: [<0.344.0>]
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 2586
    stack_size: 27
    reductions: 10857
  neighbours:

=SUPERVISOR REPORT==== 10-Jul-2017::05:25:17 ===
     Supervisor: {local,gun_sup}
     Context:    child_terminated
     Reason:     {{owner_gone,normal},
                  [{gun,loop,1,[{file,"src/gun.erl"},{line,706}]},
                   {gun,proc_lib_hack,5,[{file,"src/gun.erl"},{line,535}]},
                   {proc_lib,init_p_do_apply,3,
                             [{file,"proc_lib.erl"},{line,247}]}]}
     Offender:   [{pid,<0.364.0>},
                  {id,gun},
                  {mfargs,{gun,start_link,undefined}},
                  {restart_type,temporary},
                  {shutdown,5000},
                  {child_type,worker}]

** exception exit: {ws_upgrade_failed,404,
                                      [{<<"content-length">>,<<"0">>},
                                       {<<"date">>,
                                        <<"Mon, 10 Jul 2017 11:22:38 GMT">>},
                                       {<<"server">>,<<"Cowboy">>}]}
(my_gun@127.0.0.1)6> 

现在,我收到了404错误。牛仔正在运行,当我输入http://localhost:8080 in my browser时,我看到了一条回复消息。为什么枪给我一个404错误?

接下来,我尝试使用Gun docs中的说明发出GET请求:

StreamRef = gun:get(ConnPid, "/").

case gun:await(ConnPid, StreamRef) of
    {response, fin, Status, Headers} ->
        no_data;
    {response, nofin, Status, Headers} ->
        {ok, Body} = gun:await_body(ConnPid, StreamRef),
        io:format("~s~n", [Body])
end.

那是成功的:

=PROGRESS REPORT==== 10-Jul-2017::06:36:14 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.367.0>},{mfa,{inet_gethost_native,init,[[]]}}]

=PROGRESS REPORT==== 10-Jul-2017::06:36:14 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.366.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]
Hello Erlang!
ok
(my_gun@127.0.0.1)2> 

响应意味着我能够使用Gun与Cowboy服务器进行交互 - 但我想使用websockets。我有什么想法吗?

tip:

为了避免在枪支外壳中输入所有代码,我创建了文件~/erlang_programs/my_gun/src/my.erl

-module(my).
-compile(export_all).

get() ->
    {ok, _} = application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("localhost", 8080),
    {ok, _Protocol} = gun:await_up(ConnPid),

    StreamRef = gun:get(ConnPid, "/"),

    case gun:await(ConnPid, StreamRef) of
        {response, fin, _Status, _Headers} ->
            no_data;
        {response, nofin, _Status, _Headers} ->
            {ok, Body} = gun:await_body(ConnPid, StreamRef),
            io:format("~s~n", [Body])
    end.

ws() ->

    {ok, _} = application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("localhost", 8080),
    {ok, _Protocol} = gun:await_up(ConnPid),

    gun:ws_upgrade(ConnPid, "/websocket"),

    receive
    {gun_ws_upgrade, ConnPid, ok, Headers} ->
            upgrade_success(ConnPid, Headers);
    {gun_response, ConnPid, _, _, Status, Headers} ->
            exit({ws_upgrade_failed, Status, Headers});
    {gun_error, _ConnPid, _StreamRef, Reason} ->
            exit({ws_upgrade_failed, Reason})
    %% More clauses here as needed.
    after 1000 ->
        exit(timeout)
    end,

    gun:shutdown(ConnPid).


upgrade_success(ConnPid, Headers) ->
    io:format("Upgraded ~w. Success!~nHeaders:~n~p~n", 
              [ConnPid, Headers]).

然后是make(或gmake)命令:

 ~/erlang_programs/my_gun$ gmake run

将编译src/目录中的所有内容,并提醒您任何错误。一旦枪壳成功启动以响应gmake run,您可以执行以下操作:

(my_gun@127.0.0.1)1> my:get().

=PROGRESS REPORT==== 10-Jul-2017::06:36:14 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.367.0>},{mfa,{inet_gethost_native,init,[[]]}}]

=PROGRESS REPORT==== 10-Jul-2017::06:36:14 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.366.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]
Hello Erlang!
ok
(my_gun@127.0.0.1)2> 

对评论的回应

  

由于你获得了404,我猜你没有一个websocket处理程序   在牛仔路线中定义。

你是对的。我只有牛仔入门指南中显示的处理程序。现在,我已经为cowboy添加了websocket设置代码和websocket处理程序。我现在有路线:

hello_erlang_app.erl:

-module(hello_erlang_app).
-behaviour(application).

-export([start/2]).
-export([stop/1]).

start(_Type, _Args) ->
    Dispatch = cowboy_router:compile([
        {'_', [{"/", hello_handler, []}] },
        {'_', [{"/websocket", myws_handler, []}] }
    ]),

    {ok, _} = cowboy:start_clear(my_http_listener,
        [{port, 8080}],
        #{env => #{dispatch => Dispatch} }
    ),

    hello_erlang_sup:start_link().

stop(_State) ->
    ok.

这是我的经纪人:

-module(myws_handler).
-compile(export_all).

init(Req, State) ->
    {cowboy_websocket, Req, State}.  %Perform websocket setup

websocket_handle({text, Msg}, State) ->
    {
     reply, 
     {text, <<"Server received: ", Msg/binary>>, State}  %%Error in format here, too!
    };
websocket_handle(_Data, State) ->
    {ok, State}.

但是当我在枪炮弹中执行my:ws()时,我仍然遇到404错误:

-module(my).
-compile(export_all).

get() ->
    {ok, _} = application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("localhost", 8080),
    {ok, _Protocol} = gun:await_up(ConnPid),

    StreamRef = gun:get(ConnPid, "/"),

    case gun:await(ConnPid, StreamRef) of
        {response, fin, _Status, _Headers} ->
            no_data;
        {response, nofin, _Status, _Headers} ->
            {ok, Body} = gun:await_body(ConnPid, StreamRef),
            io:format("~s~n", [Body])
    end.

ws() ->

    {ok, _} = application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("localhost", 8080),
    {ok, _Protocol} = gun:await_up(ConnPid),

    gun:ws_upgrade(ConnPid, "/websocket"),

    receive
        {gun_ws_upgrade, ConnPid, ok, Headers} ->
            upgrade_success(ConnPid, Headers);
        {gun_response, ConnPid, _, _, Status, Headers} ->
            exit({ws_upgrade_failed, Status, Headers});
        {gun_error, _ConnPid, _StreamRef, Reason} ->
            exit({ws_upgrade_failed, Reason})
    %% More clauses here as needed.
    after 1000 ->
        exit(timeout)
    end,

    gun:shutdown(ConnPid).


upgrade_success(ConnPid, Headers) ->
    io:format("Upgraded ~w. Success!~nHeaders:~n~w~n", 
              [ConnPid, Headers]).

这是输出:

~/erlang_programs/my_gun$ gmake run
gmake[1]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
 GEN    rebar.config
gmake[1]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
 DEPEND my_gun.d
 ERLC   my.erl
 APP    my_gun
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /Users/7stud/erlang_programs/my_gun/ebin
          /Users/7stud/erlang_programs/my_gun/deps
          /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang/lib
          /Users/7stud/erlang_programs/my_gun/apps
          /Users/7stud/erlang_programs/my_gun/_rel
===> Resolved my_gun_release-1
===> rendering builtin_hook_status hook to "/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/bin/hooks/builtin/status"
===> Including Erts from /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang
===> release successfully created!
===> tarball /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/my_gun_release-1.tar.gz successfully created!
Exec: /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/erts-8.2/bin/erlexec -boot /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/my_gun_release -mode embedded -boot_var ERTS_LIB_DIR /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/lib -config /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/sys.config -args_file /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/vm.args -pa -- console
Root: /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release
/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release
heart_beat_kill_pid = 32843
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]


=PROGRESS REPORT==== 10-Jul-2017::16:26:05 ===
          supervisor: {local,sasl_safe_sup}
             started: [{pid,<0.353.0>},
                       {id,alarm_handler},
                       {mfargs,{alarm_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::16:26:05 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.352.0>},
                       {id,sasl_safe_sup},
                       {mfargs,
                           {supervisor,start_link,
                               [{local,sasl_safe_sup},sasl,safe]}},
                       {restart_type,permanent},
                       {shutdown,infinity},
                       {child_type,supervisor}]

=PROGRESS REPORT==== 10-Jul-2017::16:26:05 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.354.0>},
                       {id,release_handler},
                       {mfargs,{release_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::16:26:05 ===
         application: sasl
          started_at: 'my_gun@127.0.0.1'

=PROGRESS REPORT==== 10-Jul-2017::16:26:05 ===
          supervisor: {local,runtime_tools_sup}
             started: [{pid,<0.360.0>},
                       {id,ttb_autostart},
                       {mfargs,{ttb_autostart,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,3000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::16:26:05 ===
         application: runtime_tools
          started_at: 'my_gun@127.0.0.1'
Eshell V8.2  (abort with ^G)

(my_gun@127.0.0.1)1> my:ws().

=PROGRESS REPORT==== 10-Jul-2017::16:26:08 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.367.0>},{mfa,{inet_gethost_native,init,[[]]}}]

=PROGRESS REPORT==== 10-Jul-2017::16:26:08 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.366.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]

=CRASH REPORT==== 10-Jul-2017::16:26:08 ===
  crasher:
    initial call: gun:proc_lib_hack/5
    pid: <0.365.0>
    registered_name: []
    exception exit: {{owner_gone,normal},
                     [{gun,loop,1,[{file,"src/gun.erl"},{line,706}]},
                      {gun,proc_lib_hack,5,[{file,"src/gun.erl"},{line,535}]},
                      {proc_lib,init_p_do_apply,3,
                                [{file,"proc_lib.erl"},{line,247}]}]}
      in function  gun:proc_lib_hack/5 (src/gun.erl, line 540)
    ancestors: [gun_sup,<0.345.0>]
    messages: []
    links: [<0.346.0>]
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 610
    stack_size: 27
    reductions: 1042
  neighbours:

=SUPERVISOR REPORT==== 10-Jul-2017::16:26:08 ===
     Supervisor: {local,gun_sup}
     Context:    child_terminated
     Reason:     {{owner_gone,normal},
                  [{gun,loop,1,[{file,"src/gun.erl"},{line,706}]},
                   {gun,proc_lib_hack,5,[{file,"src/gun.erl"},{line,535}]},
                   {proc_lib,init_p_do_apply,3,
                             [{file,"proc_lib.erl"},{line,247}]}]}
     Offender:   [{pid,<0.365.0>},
                  {id,gun},
                  {mfargs,{gun,start_link,undefined}},
                  {restart_type,temporary},
                  {shutdown,5000},
                  {child_type,worker}]

** exception exit: {ws_upgrade_failed,404,
                                      [{<<"content-length">>,<<"0">>},
                                       {<<"date">>,
                                        <<"Mon, 10 Jul 2017 22:26:08 GMT">>},
                                       {<<"server">>,<<"Cowboy">>}]}
     in function  my:ws/0 (src/my.erl, line 30)

(my_gun@127.0.0.1)2> 

我保存了所有文件并重新启动了牛仔和枪支,因此我对代码所做的更改正在执行,但我仍然收到404错误。

我将路由的格式与注释中spawn_think链接的示例中的路由进行了比较,我的格式错误。这就是我现在所拥有的:

-module(hello_erlang_app).
-behaviour(application).

-export([start/2]).
-export([stop/1]).

start(_Type, _Args) ->
    Dispatch = cowboy_router:compile([
        {'_', [
               {"/", hello_handler, []},
               {"/websocket", myws_handler, []} 
        ]}
    ]),

    {ok, _} = cowboy:start_clear(my_http_listener,
        [{port, 8080}],
        #{env => #{dispatch => Dispatch} }
    ),

    hello_erlang_sup:start_link().

stop(_State) ->
    ok.

在我的枪支客户端中调整io:format()语句中的一个控制序列之后:

-module(my).
-compile(export_all).

get() ->
    ...

ws() ->
    ...

upgrade_success(ConnPid, Headers) ->
    io:format("Upgraded ~w. Success!~nHeaders:~n~p~n",   %% <*** CHANGED ~w to ~p 
              [ConnPid, Headers]).

这是输出:

~/erlang_programs/my_gun$ gmake run
gmake[1]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
 GEN    rebar.config
gmake[1]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
 DEPEND my_gun.d
 ERLC   my.erl
 APP    my_gun
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /Users/7stud/erlang_programs/my_gun/ebin
          /Users/7stud/erlang_programs/my_gun/deps
          /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang/lib
          /Users/7stud/erlang_programs/my_gun/apps
          /Users/7stud/erlang_programs/my_gun/_rel
===> Resolved my_gun_release-1
===> rendering builtin_hook_status hook to "/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/bin/hooks/builtin/status"
===> Including Erts from /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang
===> release successfully created!
===> tarball /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/my_gun_release-1.tar.gz successfully created!
Exec: /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/erts-8.2/bin/erlexec -boot /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/my_gun_release -mode embedded -boot_var ERTS_LIB_DIR /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/lib -config /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/sys.config -args_file /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/vm.args -pa -- console
Root: /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release
/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release
heart_beat_kill_pid = 34141
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]


=PROGRESS REPORT==== 10-Jul-2017::16:50:53 ===
          supervisor: {local,sasl_safe_sup}
             started: [{pid,<0.353.0>},
                       {id,alarm_handler},
                       {mfargs,{alarm_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::16:50:53 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.352.0>},
                       {id,sasl_safe_sup},
                       {mfargs,
                           {supervisor,start_link,
                               [{local,sasl_safe_sup},sasl,safe]}},
                       {restart_type,permanent},
                       {shutdown,infinity},
                       {child_type,supervisor}]

=PROGRESS REPORT==== 10-Jul-2017::16:50:53 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.354.0>},
                       {id,release_handler},
                       {mfargs,{release_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::16:50:53 ===
         application: sasl
          started_at: 'my_gun@127.0.0.1'

=PROGRESS REPORT==== 10-Jul-2017::16:50:53 ===
          supervisor: {local,runtime_tools_sup}
             started: [{pid,<0.360.0>},
                       {id,ttb_autostart},
                       {mfargs,{ttb_autostart,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,3000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::16:50:53 ===
         application: runtime_tools
          started_at: 'my_gun@127.0.0.1'
Eshell V8.2  (abort with ^G)
(my_gun@127.0.0.1)1> my:ws().

=PROGRESS REPORT==== 10-Jul-2017::16:50:57 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.367.0>},{mfa,{inet_gethost_native,init,[[]]}}]

=PROGRESS REPORT==== 10-Jul-2017::16:50:57 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.366.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]
Upgraded <0.365.0>. Success!
Headers:
[{<<"connection">>,<<"Upgrade">>},
 {<<"date">>,<<"Mon, 10 Jul 2017 22:50:56 GMT">>},
 {<<"sec-websocket-accept">>,<<"S1w7rWXToZefi/NOEcDAEDb4yEU=">>},
 {<<"server">>,<<"Cowboy">>},
 {<<"upgrade">>,<<"websocket">>}]
ok
(my_gun@127.0.0.1)2> 

我已经达到了论坛对文字的限制,所以请查看我的回答,了解我实际上是如何使用websocket发送和接收数据的。

2 个答案:

答案 0 :(得分:2)

评论讨论中的问题/建议摘要

  1. 为了运行你的Erlang应用程序(在这种情况下包括枪作为依赖项),你需要有一个可以被shell发现的beam和.app文件的路径。使用erlang.mk时,最简单的方法是使用make run

  2. 运行版本
  3. 在牛仔方面,要正确处理Websocket,您需要在牛仔路线中定义一个处理程序。请参阅Cowboy Websocket example

  4. 中的示例

    有关在Gun中处理Websocket的更多详细信息,另请参阅Gun user guide

答案 1 :(得分:0)

成功!

〜/ erlang_programs / my_gun / SRC / my.erl:

4

在牛仔方面:

-module(my).
-compile(export_all).

get() ->
    ...

ws() ->

    {ok, _} = application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("localhost", 8080),
    {ok, _Protocol} = gun:await_up(ConnPid),

    gun:ws_upgrade(ConnPid, "/websocket"),

    receive
    {gun_ws_upgrade, ConnPid, ok, Headers} ->
            upgrade_success(ConnPid, Headers);
    {gun_response, ConnPid, _, _, Status, Headers} ->
            exit({ws_upgrade_failed, Status, Headers});
    {gun_error, _ConnPid, _StreamRef, Reason} ->
            exit({ws_upgrade_failed, Reason})
    %% More clauses here as needed.
    after 1000 ->
        exit(timeout)
    end,

    gun:shutdown(ConnPid).


upgrade_success(ConnPid, Headers) ->
    io:format("Upgraded ~w. Success!~nHeaders:~n~p~n", 
              [ConnPid, Headers]),

    gun:ws_send(ConnPid, {text, "It's raining!"}),

    receive
        {gun_ws, ConnPid, {text, Msg} } ->
            io:format("~s~n", [Msg])
    end.

这是输出:

-module(myws_handler).
-compile(export_all).

init(Req, State) ->
    {cowboy_websocket, Req, State}.  %Perform websocket setup

websocket_handle({text, Msg}, State) ->
    {
     reply, 
     {text, io_lib:format("Server received: ~s", [Msg]) },
     State
    };
websocket_handle(_Other, State) ->  %Ignore
    {ok, State}.