Erlang中有没有类似于unix下的IO多路复用机制
一个unix程序希望从多个文件描述符中读取数据,直接使用read系统调用去处理有可能会阻塞在一个文件描述符上,而不能处理其他的文件描述符,因此系统提供了select系统调用对多个文件描述符进行监测。
在erlang系统中也存在类似的问题,如果process既需要读文件又需要接收消息,该如何处理了?当然最简单的方法是创建一个新的process,原有的process执行IO阻塞操作,新的process执行接收消息的阻塞操作。不知道Erlang中有没有类似于unix下的IO多路复用机制,使用一个process就可以监测两个信号源。
具体以下面的chat server例子来说,程序中的main process执行accept操作,client_manager process执行client集合的管理操作,我希望main process能够和client manager process合并,这样可以简化程序的逻辑。
多谢回答。
- -module(basicchat).
- -export([listen/1]).
- %% 侦听socket的 TCP 选项。第一个 list 元语
- %% 表示我们想接收数据的是字节列表(如
- %% 字符串),而不是二进制的对象。
- %% 其他的参数请参考 Erlang 文档。
- -define(TCP_OPTIONS,[list, {packet, 0}, {active, false}, {reuseaddr, true}]).
- %% 侦听指定的端口,接受第一个连接,
- %% 然后启动 echo 循环。同时要启动 client_manager,
- %% 这个是服务器的入口点。
- listen(Port) ->
- Pid = spawn(fun() -> manage_clients([]) end),
- register(client_manager, Pid),
- {ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
- do_accept(LSocket).
- %% 接受以后创建处理过程,
- %% 末尾调用 do_accept 再次进入侦听
- %% 还要通知 client_manager 有新的连接要加入
- do_accept(LSocket) ->
- {ok, Socket} = gen_tcp:accept(LSocket),
- spawn(fun() -> handle_client(Socket) end),
- client_manager ! {connect, Socket},
- do_accept(LSocket).
- %% handle_client/1 替换掉 do_echo/1 ,因为现在所有事情都要
- %% 通过 client_manager 完成。断开时通知 client_manager
- %% socket 已经关闭,数据就当是发送完成了。
- handle_client(Socket) ->
- case gen_tcp:recv(Socket, 0) of
- {ok, Data} ->
- client_manager ! {data, Data},
- handle_client(Socket);
- {error, closed} ->
- client_manager ! {disconnect, Socket}
- end.
- %% 维护 socket 列表,处理连接和断开消息,
- %% 并互相传递数据
- manage_clients(Sockets) ->
- receive
- {connect, Socket} ->
- io:fwrite("Socket connected: ~w~n", [Socket]),
- NewSockets = [Socket | Sockets];
- {disconnect, Socket} ->
- io:fwrite("Socket disconnected: ~w~n", [Socket]),
- NewSockets = lists:delete(Socket, Sockets);
- {data, Data} ->
- send_data(Sockets, Data),
- NewSockets = Sockets
- end,
- manage_clients(NewSockets).
- %% 给列表中的所有 socket 发消息。通过 lists:foreach/2 遍历
- %% 列表中的每个 socket,再调用 gen_tcp:send 来发送数据
- send_data(Sockets, Data) ->
- SendData = fun(Socket) ->
- gen_tcp:send(Socket, Data)
- end,
- lists:foreach(SendData, Sockets).
复制代码
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
小弟初学erlang,?TCP_OPTIONS之前的?代表什么意思?