【发布时间】:2018-04-06 20:19:54
【问题描述】:
我尝试在我的 Java 应用程序中使用 Erlang 实现服务器。 似乎我的服务器正在工作,但仍然充满错误和死点。 我需要将 Java 应用程序解析的 JSON 文件接收到地图中,并将其发送回所有客户端,包括上传文件的客户端。 同时,我需要跟踪谁发出了请求以及消息的哪一部分被发送,以防出现任何问题,客户端应该从此时开始重新启动,而不是从头开始。除非客户端离开应用程序,否则它应该重新启动。
我的三段代码如下:
app.erl
-module(erlServer_app).
-behaviour(application).
%% Application callbacks
-export([start/2, stop/1]).
%%%===================================================================
%%% Application callbacks
%%%===================================================================
start(_StartType, _StartArgs) ->
erlServer_sup:start_link().
stop(_State) ->
ok.
supervisor.erl:
-module(erlServer_sup).
-behaviour(supervisor).
%% API
-export([start_link/0]).
%% Supervisor callbacks
-export([init/1, start_socket/0, terminate_socket/0, empty_listeners/0]).
-define(SERVER, ?MODULE).
%%--------------------------------------------------------------------
%% @doc
%% Starts the supervisor
%%
%% @end
%%--------------------------------------------------------------------
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
%%%===================================================================
%%% Supervisor callbacks
%%%===================================================================
init([]) -> % restart strategy 'one_for_one': if one goes down only that one is restarted
io:format("starting...~n"),
spawn_link(fun() -> empty_listeners() end),
{ok,
{{one_for_one, 5, 30}, % The flag - 5 restart within 30 seconds
[{erlServer_server, {erlServer_server, init, []}, permanent, 1000, worker, [erlServer_server]}]}}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
start_socket() ->
supervisor:start_child(?MODULE, []).
terminate_socket() ->
supervisor:delete_child(?MODULE, []).
empty_listeners() ->
[start_socket() || _ <- lists:seq(1,20)],
ok.
server.erl:(我调试了很多io:format。)
-module(erlServer_server).
%% API
-export([init/0, start_server/0]).
%% Defining the port used.
-define(PORT, 8080).
%%%===================================================================
%%% API
%%%===================================================================
init() ->
start_server().
%%%===================================================================
%%% Server callbacks
%%%===================================================================
start_server() ->
io:format("Server started.~n"),
Pid = spawn_link(fun() ->
{ok, ServerSocket} = gen_tcp:listen(?PORT, [binary, {packet, 0},
{reuseaddr, true}, {active, true}]),
io:format("Baba~p", [ServerSocket]),
server_loop(ServerSocket) end),
{ok, Pid}.
server_loop(ServerSocket) ->
io:format("Oba~p", [ServerSocket]),
{ok, Socket} = gen_tcp:accept(ServerSocket),
Pid1 = spawn(fun() -> client() end),
inet:setopts(Socket, [{packet, 0}, binary,
{nodelay, true}, {active, true}]),
gen_tcp:controlling_process(Socket, Pid1),
server_loop(ServerSocket).
%%%===================================================================
%%% Internal functions
%%%===================================================================
client() ->
io:format("Starting client. Enter \'quit\' to exit.~n"),
Client = self(),
{ok, Sock} = gen_tcp:connect("localhost", ?PORT, [{active, false}, {packet, 2}]),
display_prompt(Client),
client_loop(Client, Sock).
%%%===================================================================
%%% Client callbacks
%%%===================================================================
send(Sock, Packet) ->
{ok, Sock, Packet} = gen_tcp:send(Sock, Packet),
io:format("Sent ~n").
recv(Packet) ->
{recv, ok, Packet} = gen_tcp:recv(Packet),
io:format("Received ~n").
display_prompt(Client) ->
spawn(fun () ->
Packet = io:get_line("> "),
Client ! {entered, Packet}
end),
Client ! {requested},
ok.
client_loop(Client, Sock) ->
receive
{entered, "quit\n"} ->
gen_tcp:close(Sock);
{entered, Packet} ->
% When a packet is entered we receive it,
recv(Packet),
display_prompt(Client),
client_loop(Client, Sock);
{requested, Packet} ->
% When a packet is requested we send it,
send(Sock, Packet),
display_prompt(Client),
client_loop(Client, Sock);
{error, timeout} ->
io:format("Send timeout, closing!~n", []),
Client ! {self(),{error_sending, timeout}},
gen_tcp:close(Sock);
{error, OtherSendError} ->
io:format("Some other error on socket (~p), closing", [OtherSendError]),
Client ! {self(),{error_sending, OtherSendError}},
gen_tcp:close(Sock)
end.
这是我正在做的第一台服务器,我可能在中间迷路了。当我跑步时,它似乎正在工作,但挂起。有人能帮我吗?我的本地主机永远不会加载它永远加载的任何东西。
我的 java 应用程序如何从同一个端口接收它?
我必须使用 Erlang 并且我必须使用端口连接到 Java 应用程序。
谢谢你帮助我!
【问题讨论】:
-
当您执行
{ok, Socket} = gen_tcp:accept时,您已经连接到客户端。 This 是您需要传递给客户端的套接字。所以client/0应该是client/1并且它应该接受连接的套接字。除非您的服务器正在调用 另一个 服务器,否则您不需要从此代码调用gen_tcp:connect。 Erlang 比 Java 简单得多。在全局状态下,后台没有发生客观的事情。如果您不将套接字传递给函数,则该套接字对该函数不可见。 -
@zxq9 感谢您的回答。但是在 client/1 中,当你说我需要接受连接的套接字时,我该怎么做,我以为是 gen_tcp:connect 函数?此外,当我运行代码时,它永远不会进入这一步。最后打印的阶段是 server_loop 中的第一个 io。
-
是的,您已经接受了来自客户端的连接。稍后我会写一个例子。我认为您可能还想查看 Erlang 文档中的 gen_tcp 套接字处理示例。 erlang.org/doc/man/gen_tcp.html
-
好的,我为您编写了一个带注释和精简的套接字服务示例(因此我可以在将来参考它,因为这会出现很多)。这使您能够处理套接字——下一个障碍将是解释您通过该套接字接收到的任何内容。我自己没有使用过 Java 端口实用程序,但我有使用过 BERT,如果你需要在 Java(或任何其他)程序和二郎一。如果您有更多问题,请联系Erlang/OTP chat。
标签: erlang erlang-ports