免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7016 | 回复: 1

[其他] Erlang中有没有类似于unix下的IO多路复用机制 [复制链接]

论坛徽章:
0
发表于 2010-05-25 22:08 |显示全部楼层
一个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合并,这样可以简化程序的逻辑。

多谢回答。

  1. -module(basicchat).
  2. -export([listen/1]).

  3. %% 侦听socket的 TCP 选项。第一个 list 元语
  4. %% 表示我们想接收数据的是字节列表(如
  5. %% 字符串),而不是二进制的对象。
  6. %% 其他的参数请参考 Erlang 文档。

  7. -define(TCP_OPTIONS,[list, {packet, 0}, {active, false}, {reuseaddr, true}]).

  8. %% 侦听指定的端口,接受第一个连接,
  9. %% 然后启动 echo 循环。同时要启动 client_manager,
  10. %% 这个是服务器的入口点。

  11. listen(Port) ->
  12.     Pid = spawn(fun() -> manage_clients([]) end),
  13.     register(client_manager, Pid),
  14.     {ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
  15.     do_accept(LSocket).

  16. %% 接受以后创建处理过程,
  17. %% 末尾调用 do_accept 再次进入侦听
  18. %% 还要通知 client_manager 有新的连接要加入

  19. do_accept(LSocket) ->
  20.     {ok, Socket} = gen_tcp:accept(LSocket),
  21.     spawn(fun() -> handle_client(Socket) end),
  22.     client_manager ! {connect, Socket},
  23.     do_accept(LSocket).

  24. %% handle_client/1 替换掉 do_echo/1 ,因为现在所有事情都要
  25. %% 通过 client_manager 完成。断开时通知 client_manager
  26. %% socket 已经关闭,数据就当是发送完成了。

  27. handle_client(Socket) ->
  28.     case gen_tcp:recv(Socket, 0) of
  29.         {ok, Data} ->
  30.             client_manager ! {data, Data},
  31.             handle_client(Socket);
  32.         {error, closed} ->
  33.             client_manager ! {disconnect, Socket}
  34.     end.

  35. %% 维护 socket 列表,处理连接和断开消息,
  36. %% 并互相传递数据

  37. manage_clients(Sockets) ->
  38.     receive
  39.         {connect, Socket} ->
  40.             io:fwrite("Socket connected: ~w~n", [Socket]),
  41.             NewSockets = [Socket | Sockets];
  42.         {disconnect, Socket} ->
  43.             io:fwrite("Socket disconnected: ~w~n", [Socket]),
  44.             NewSockets = lists:delete(Socket, Sockets);
  45.         {data, Data} ->
  46.             send_data(Sockets, Data),
  47.             NewSockets = Sockets
  48.     end,
  49.     manage_clients(NewSockets).

  50. %% 给列表中的所有 socket 发消息。通过 lists:foreach/2 遍历
  51. %% 列表中的每个 socket,再调用 gen_tcp:send 来发送数据

  52. send_data(Sockets, Data) ->
  53.     SendData = fun(Socket) ->
  54.                        gen_tcp:send(Socket, Data)
  55.                end,
  56.     lists:foreach(SendData, Sockets).
复制代码

论坛徽章:
0
发表于 2011-10-20 14:13 |显示全部楼层
小弟初学erlang,?TCP_OPTIONS之前的?代表什么意思?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP