Erlang工作进程

Erlang工作进程,erlang,message,message-passing,Erlang,Message,Message Passing,我对Erlang非常陌生,但是我一直在尝试创建一个简单的客户机-服务器实现。服务器将假设创建工作进程来在“数据库”中执行“繁重的工作”,然后将计算出的值返回给客户端 我目前的步骤是: 创建一个服务器进程 产生一个工人 根据客户的输入,向员工发送一些要做的工作(这是我困惑的地方) 将数据从工作者发送回客户端 下面是一些示例代码 -module(server). -compile(export_all). server() -> receive {From, {cli

我对Erlang非常陌生,但是我一直在尝试创建一个简单的客户机-服务器实现。服务器将假设创建工作进程来在“数据库”中执行“繁重的工作”,然后将计算出的值返回给客户端

我目前的步骤是:

  • 创建一个服务器进程
  • 产生一个工人
  • 根据客户的输入,向员工发送一些要做的工作(这是我困惑的地方)
  • 将数据从工作者发送回客户端
  • 下面是一些示例代码

    -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
    不会打印任何内容。