Erlang工作进程
我对Erlang非常陌生,但是我一直在尝试创建一个简单的客户机-服务器实现。服务器将假设创建工作进程来在“数据库”中执行“繁重的工作”,然后将计算出的值返回给客户端 我目前的步骤是:Erlang工作进程,erlang,message,message-passing,Erlang,Message,Message Passing,我对Erlang非常陌生,但是我一直在尝试创建一个简单的客户机-服务器实现。服务器将假设创建工作进程来在“数据库”中执行“繁重的工作”,然后将计算出的值返回给客户端 我目前的步骤是: 创建一个服务器进程 产生一个工人 根据客户的输入,向员工发送一些要做的工作(这是我困惑的地方) 将数据从工作者发送回客户端 下面是一些示例代码 -module(server). -compile(export_all). server() -> receive {From, {cli
-module(server).
-compile(export_all).
server() ->
receive
{From, {client, Name}} ->
io:format("Server has received request for ~p from ~p~n", [Name, From]),
Worker = spawn(server, getNameFromDataBase(self()),[]),
Worker ! Name,
From ! LastName,%%data returned from worker
server();
{database, LastName} ->
Data = LastName,
server()
end.
getNameFromDataBase(Server_Address) ->
receive
{name, Name} ->
timer:sleep(5000), %doing difficult work!
Server_Address ! {database, "Johnson"}
end.
client(Server_Address) ->
Server_Address ! {self(), {client, "Jim"}},
receive
{server, LastName} ->
io:format("Server got person's last name~p~n", LastName)
end.
如何使您从工作人员处收到的数据能够被查看并发送到客户端 您将从receive的
{database,LastName}->
分支中的工作者那里获得消息。只需在消息本身中包含您需要处理的信息:
server() ->
receive
{From, {client, Name}} ->
io:format("Server has received request for ~p from ~p~n", [Name, From]),
Worker = spawn(server, getNameFromDataBase, [self()]),
Worker ! {name, From, Name},
server();
{database, From, LastName} ->
From ! LastName,
server()
end.
getNameFromDataBase(Server_Address) ->
receive
{name, From, Name} ->
timer:sleep(5000), %doing difficult work!
Server_Address ! {database, From, "Johnson"}
end.
请注意,需要在列表中传递参数(spawn的第三个参数)。另外,如果您创建worker只是为了立即发送一条消息,那么您也可以将其内容作为参数传递;我在这里做这个改变不是为了更容易看到主要的改变
或者,您可以在服务器状态下存储与
工作者相对应的(server()
)中的。我可以看出服务器进程存在两个主要问题:
将消息从服务器发送到数据库工作程序李>
将服务器从worker接收到的消息发送回客户端
向工作人员发送消息
以下L8-L10中的代码行不正确
%% ...
Worker = spawn(server, getNameFromDataBase(self()), []),
Worker ! Name,
From ! LastName,
%% ...
要将函数生成为进程,必须在spawn/3
的第三个参数中为函数提供作为列表成员的任何参数,而不是直接调用函数
Worker = spawn(server, getNameFromDataBase, [self()]),
只将Name
发送到Worker
将不被注意,因为getNameFromDataBase
需要{Name,Name}
。这应该改为
Worker ! {name, Name}
向客户端发送结果(姓氏)
从中发送是没有意义的!L10上的LastName
,因为您尚未收到LastName
。当服务器从工作程序接收到{database,LastName}
时,应该将其移动到第二个匹配表达式。
此外,客户端
需要的是{server,LastName}
,而不是LastName
。所以它应该是来自!{server,LastName}
然而,有一个问题。您无法从该范围中的
访问,因为它从未定义过
%% ...
{database, LastName} ->
From ! {server, LastName}, % `From` is not defined
server()
%% ...
不必更改消息元组,您可能需要定义另一个server/1
函数,如下所示:
server(ClientPID) ->
receive
{_, LastName} ->
ClientPID ! {server, LastName},
server()
end.
并从服务器/0
调用此命令:
server() ->
receive
{From, {client, Name}} ->
io:format("Server has received request for ~p from ~p~n", [Name, From]),
Worker = spawn(?MODULE, getNameFromDataBase, [self()]),
Worker ! {name, Name},
server(From) % call `server/1` with the client's PID
end.
最后,要总结所有内容,如果您还没有,请创建一个启动函数来生成服务器
和客户端
进程。以下是完整的代码:
server() ->
receive
{From, {client, Name}} ->
io:format("Server has received request for ~p from ~p~n", [Name, From]),
Worker = spawn(?MODULE, getNameFromDataBase, [self()]),
Worker ! {name, Name},
server(From)
end.
server(ClientPID) ->
receive
{_, LastName} ->
ClientPID ! {server, LastName},
server()
end.
getNameFromDataBase(ServerAddr) ->
receive
{name, Name} ->
io:format("worker received ~p~n",[Name]),
timer:sleep(5000),
ServerAddr ! {database, "Johnson"}
end.
client(ServerPID) ->
ServerPID ! {self(),{client, "Jim"}},
receive
{server, LastName} ->
io:format("Client got person's last name ~p from Server ~n", [LastName])
end.
run() ->
ServerPID = spawn(?MODULE, server, []),
spawn(?MODULE, client, [ServerPID]).
最后一个提示:不要使用export\u all
compile选项。仅导出必要的函数以实现良好的封装。在这种情况下,客户端需要{server,LastName}
因此只需从发送LastName
!LastName
不会打印任何内容。