Erlang udp工作程序-希望在同一端口上有更多udp侦听器

Erlang udp工作程序-希望在同一端口上有更多udp侦听器,erlang,udp,pattern-matching,actor,Erlang,Udp,Pattern Matching,Actor,我正在用Erlang制作一个游戏服务器,我希望每个连接的客户端都有一个进程。这个过程应该负责处理客户端发送到服务器的所有UDP消息,必要时进行处理和回复 我如何做到这一点?我知道,使用TCP,我可以放置任意数量的侦听器来运行该函数 gen_tcp:accept(ListenSocket) 它会阻止工作人员,直到有工作可用,等等。我也想要udp的这种行为,但我一直在尝试制作一个简单的示例,生成一个新的进程,根据ip和端口匹配每个udp数据包,以查看哪个播放器发送了数据包,为自己选择这些数据包,忽

我正在用Erlang制作一个游戏服务器,我希望每个连接的客户端都有一个进程。这个过程应该负责处理客户端发送到服务器的所有UDP消息,必要时进行处理和回复

我如何做到这一点?我知道,使用TCP,我可以放置任意数量的侦听器来运行该函数

gen_tcp:accept(ListenSocket)
它会阻止工作人员,直到有工作可用,等等。我也想要udp的这种行为,但我一直在尝试制作一个简单的示例,生成一个新的进程,根据ip和端口匹配每个udp数据包,以查看哪个播放器发送了数据包,为自己选择这些数据包,忽略其余的数据包

loop({Sock, Ip, Port}) ->
    receive
        {udp, Sock, Ip, Port, Msg} ->
            do_stuff & loop, etc.
    end
end.
这是否与循环到消息的Ip匹配?为了实现这一点,我需要任何其他UDP侦听器不匹配特定的数据包,以便工作人员在任何给定的时间获取它应该获取的每条消息,对吗?如果另一个“通用”UDP侦听器侦听,它可能会在工作进程之前拾取消息


所以我问这个方法是否有效,或者我是否会得到一个错误,说它不是套接字的所有者或者类似的东西。到目前为止,我还没有让任何工作进程实际接收任何消息,所以我不确定这是因为不匹配还是因为套接字只向当前控制进程发送消息,我想这会使我的计划变得不可能。

你问题的标题和措辞表明你正在尝试使用UDP套接字,比如TCP

TCP和UDP是不同的协议 TCP是一种面向连接的协议。客户端连接到服务器,给定的服务器每个连接将有一个套接字,外加一个用于侦听的套接字。操作系统的网络堆栈将传入的数据包路由到侦听套接字或正确连接的套接字

UDP是无连接的您的程序将只有一个UDP套接字。它将接收到给定端口的所有UDP数据包。无法生成进程并使其在同一端口上侦听。因此,在标题中写入时,同一端口上不能有更多udp侦听器

考虑Erlang实现 TCP的常见设计模式是让一个进程处理侦听套接字,为每个连接的套接字生成新的工作进程

由于您尝试使用UDP实现类似的功能,因此需要使用TCP执行网络堆栈为您所做的操作。您可以让一个进程接收数据包并将其转发到适当的工作进程,如果需要,根据源端口和IP地址生成数据包。该过程应维护所有活动“连接”的表,即所有活动“流”数据包

还请注意,UDP没有关闭机制,因此您应该依赖超时,可能还有协议中的附加机制

按照您在注释中的建议,在每个进程上的单个套接字上进行过滤是不可能的,因为处于活动模式的Erlang套接字将数据包发送到单个进程(控制进程)。您可以想象一些架构,其中数据包被广播到所有进程,每个进程都进行过滤以选择感兴趣的数据包

但是,您将看到,这在您的特定场景中没有意义,因为您还需要一种机制来确定是否应该生成工作进程,并且该机制最终将告诉您哪个进程应该处理传入的数据包。如果几个工人处理同一条消息,这可能是有意义的

让我们通过一些代码具体了解一下:

server_loop(Workers) ->
    receive
        {udp, Sock, Ip, Port, Msg} = UDPPacket ->
            % find out if we need to spawn a new worker.
            % typically, Workers is a gb_trees:tree().
            NewWorkers = case gb_trees:lookup({Ip, Port}, Workers) of
                none ->
                    NewWorkerPid = spawn_link(fun() -> worker_loop(Ip, Port) end),
                    gb_trees:insert(NewWorkerPid, Workers);
                {value, _WorkerPid} -> Workers  %% <- look, we have the worker!
            end,
            % broadcast to all workers.
            lists:foreach(fun({_, Worker} ->
                Worker ! UDPPacket
            end, gb_trees:to_list(NewWorkers)),
            server_loop(NewWorkers);
        % ... timeout callbacks from workers would go here
    end.

问题的标题和措辞表明您正在尝试使用UDP套接字,如TCP

TCP和UDP是不同的协议 TCP是一种面向连接的协议。客户端连接到服务器,给定的服务器每个连接将有一个套接字,外加一个用于侦听的套接字。操作系统的网络堆栈将传入的数据包路由到侦听套接字或正确连接的套接字

UDP是无连接的您的程序将只有一个UDP套接字。它将接收到给定端口的所有UDP数据包。无法生成进程并使其在同一端口上侦听。因此,在标题中写入时,同一端口上不能有更多udp侦听器

考虑Erlang实现 TCP的常见设计模式是让一个进程处理侦听套接字,为每个连接的套接字生成新的工作进程

由于您尝试使用UDP实现类似的功能,因此需要使用TCP执行网络堆栈为您所做的操作。您可以让一个进程接收数据包并将其转发到适当的工作进程,如果需要,根据源端口和IP地址生成数据包。该过程应维护所有活动“连接”的表,即所有活动“流”数据包

还请注意,UDP没有关闭机制,因此您应该依赖超时,可能还有协议中的附加机制

按照您在注释中的建议,在每个进程上的单个套接字上进行过滤是不可能的,因为处于活动模式的Erlang套接字将数据包发送到单个进程(控制进程)。您可以想象一些架构,其中数据包被广播到所有进程,每个进程都进行过滤以选择感兴趣的数据包

但是,您将看到,这在您的特定场景中没有意义,因为您还需要一种机制来确定是否应该生成工作进程,并且该机制最终将告诉您哪个进程应该处理传入的数据包。如果几个工人处理同一条消息,这可能是有意义的

让我们通过一些代码具体了解一下:

server_loop(Workers) ->
    receive
        {udp, Sock, Ip, Port, Msg} = UDPPacket ->
            % find out if we need to spawn a new worker.
            % typically, Workers is a gb_trees:tree().
            NewWorkers = case gb_trees:lookup({Ip, Port}, Workers) of
                none ->
                    NewWorkerPid = spawn_link(fun() -> worker_loop(Ip, Port) end),
                    gb_trees:insert(NewWorkerPid, Workers);
                {value, _WorkerPid} -> Workers  %% <- look, we have the worker!
            end,
            % broadcast to all workers.
            lists:foreach(fun({_, Worker} ->
                Worker ! UDPPacket
            end, gb_trees:to_list(NewWorkers)),
            server_loop(NewWorkers);
        % ... timeout callbacks from workers would go here
    end.

我知道两者的区别。我想使用UDP,就好像它是TCP一样,我想让一个特定的进程处理一个特定的客户端,因为我将通过