【问题标题】:Erlang inets httpc connect to local inets httpdErlang inets httpc 连接到本地 inets httpd
【发布时间】:2015-05-09 22:40:08
【问题描述】:

我正在尝试使用 httpd 实现一个模块,该模块处理进程的 HTTP 获取请求。基本上它处理传入的 get 请求,解析 get 参数并在节点上调用同步 gen_server 方法,该方法启动了 http 服务器。然后,它返回一些带有来自同步调用的返回值的 HTML。一切正常,直到我用浏览器测试它(Chrome,Firefox 最新版本工作)。但是我需要实现一个 HTTP 转发功能,其中 http 服务器可以使用给定的参数调用另一个 URL。我用httpc试了一下:

httpc:request(get, {"http://localhost:55556/httpfront:get?key=1", []}, [], []).

但是抛出了以下错误:

{error,{failed_connect,[{to_address,{"localhost",55556}},
                        {inet,[inet],econnrefused}]}}

你能帮帮我吗?我错过了什么?

附言。其他网站,例如stackoverflow.com 与上述httpc:request(...) 一起使用。

配置: 我启动node.erl,节点在另一个模块中启动httpfront.erl httpd守护进程,get请求在httpfront处理。我这样做了几次(启动更多节点),现在我想从一个带有 httpc:request(...) 的 httpfront 实例连接到另一个。所有的 HTTP 处理程序都在本地主机上启动,但不同的非专有端口。

node.erl:

http_listener() ->
    httpfront:start().

start() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
...

httpfront.erl:

start() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []),
%this is the port number, it increments on each new node
    P = 55556,
    % the corresponding url is: http://localhost:port/
    % command are accesible this way:
    % port is from 55556 until end of valid port range, increments on new node join
    % http://localhost:55556/httpfront:get?key=thisisashortkey
    inets:start(),
    inets:start(httpd, [
        {modules, [
            mod_alias, 
            mod_auth, 
            mod_esi, 
            mod_actions, 
            mod_cgi, 
            mod_dir, 
            mod_get, 
            mod_head, 
            mod_log, 
            mod_disk_log
        ]},
        {port,P},
        {server_name,"httpfront"},
        {server_root,"log"},
        {document_root,"www"},
        {erl_script_alias, {"", [httpfront]}},
        {error_log, "error.log"},
        {security_log, "security.log"},
        {transfer_log, "transfer.log"},
        {mime_types,[
            {"html","text/html"}
            ]}
        ]),
        io:format("OK. Good to go.~n").

    get(SessionID, _Env, Input) ->
    % this get() is a gen_server synchronous call on the inside
    Result = node:get(Input),

    mod_esi:deliver(SessionID, [
        "Content-Type: text/html\r\n\r\n", 
        "<html><body>",
        "Get<br>",
        "Key=" ++ Value,
        "<br>Result=" ++ Result,
        "</body></html>"


    ]).
    ...

正如我所说,现在我终于尝试从另一个节点调用它,但我得到了错误:

httpc:request(get, {"http://localhost:55556/httpfront:get?key=1", []}, [], []).
{error,{failed_connect,[{to_address,{"localhost",55556}},
                        {inet,[inet],econnrefused}]}}

感谢任何帮助和建议。谢谢。

【问题讨论】:

  • 我怀疑您遇到了 IPv4 与 IPv6 问题,其中 localhost 为您的客户端解析为 ::1,但您的服务器仅在 127.0.0.1 上侦听。
  • @SteveVinoski 谢谢,我也用httpc:request(get, {"http://127.0.0.1:55556/httpfront:get?key=1", []}, [], []). 尝试过,但出现同样的错误。此外,如果我在 localhost 上的任何未占用端口上启动不同的 Web 服务器(使用 nginx 的空白项目),则上述请求可以毫无问题地连接到该服务器(在 httpc 请求中使用 localhost)。我禁用了我的防病毒软件和防火墙,但没有任何变化。你指的是这个吗?
  • 是的,类似的。也有可能httpd 正在收听::1,但您的客户正在尝试127.0.0.1。如果您让客户尝试使用计算机的非本地 IP 地址而不是 localhost,会发生什么情况?
  • 我的公共 IP 地址和本地 192.168.x.x 的相同错误 (econnrefused)。由于我不熟悉 IPv6,因此无法按照您的建议尝试 ::1。你能举个例子吗?它是否有可能默认映射到 IPv6?我没有更改 httpd 选项。
  • 您确定httpd 在您认为的位置运行吗? netstat -an | grep 55556 是否在所有接口的 TCP 侦听模式下显示该端口?

标签: apache http erlang gen-server inets


【解决方案1】:

尝试将{ipfamily, inet} 作为httpd start 调用的选项列表成员传递,以使其侦听 IPv4 而不是 IPv6。此外,由于您可能只需要localhost 连接,因此您也可以考虑传递{bind_address, {127,0,0,1}} 选项。

【讨论】:

    猜你喜欢
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 2018-08-16
    • 2011-07-09
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多