Home > misc > 关于gen_tcp:controlling_process函数的使用

关于gen_tcp:controlling_process函数的使用

December 13th, 2008 :: Godwit

初学Erlang,碰到一个小小的问题,拿出来跟大家分享一下。:)
想用gen_server写一个简单的客户端,要求可以无阻塞的接收。开始想的很简单,关键代码如下。

  1. start( Host, Port ) ->
  2.   io:format(Client is starting…~n),
  3.   gen_server:start_link( {local, ?MODULE}, ?MODULE, [Host, Port], [] ).
  4.  
  5. init( [Host, Port] ) ->
  6. { ok, Socket } = gen_tcp:connect( Host, Port,
  7.     [ binary, { packet, 4 }, { active, true } ] ),
  8.   Pid = spawn( fun() -> sendRecvMsg( Socket ) end ),
  9.   %%该处加入gen_tcp:controlling_process( Socket, Pid ),
  10.   Data = #data{ socket = Pid },
  11.   { ok, Data }.
  12.  
  13. sendRecvMsg( Socket ) ->
  14.   receive
  15.     { tcp, Socket, Bin } ->
  16.       %% 注意:此处收不到消息
  17.       sendRecvMsg( Socket );
  18.     { send, Message } ->
  19.       gen_tcp:send( Socket, Message ),
  20.       %% 注意:此处可以收到消息,但是显然是阻塞接收的。
  21.       receive
  22.         { tcp, Socket, Bin } ->
  23.           io:format(Receive something!~n)
  24.         after 1000 ->
  25.           sendRecvMsg( Socket)
  26.       end
  27.   end.

想了好多方法,没有解决,回头认真的把书相关章节读了读,顿悟(参见《Erlang程序设计》第196页):
创建一个套接字的进程(通过调用gen_tcp:accept或gen_tcp:connect)也就是所说的该套接字的控制进程。这个套接字所收到的任何消息都会转发给这个控制进程,如果控制进程消亡,那么该套接字也会自行关闭。我们可以通过gen_tcp:controlling_process(Socket, NewPid)函数来把一个套接字的控制进程改为新的控制进程NewPid。
所以,在spawn之后加入如下语句:

gen_tcp:controlling_process( Socket, Pid ),

就可以了。

misc

  1. sw2wolf
    December 14th, 2008 at 11:01 | #1

    代码能否好好排一下, 看起来太乱!!!

  2. Godwit
    December 14th, 2008 at 12:05 | #2

    @sw2wolf
    稍微改了下,希望看起来可以舒服些。
    WordPress的缩进功能我掌握的不好。。。
    一行一行的改太浪费时间了。。。

  3. jackyz
    December 15th, 2008 at 09:11 | #3

    @Godwit,代码排版,可以参看顶部菜单中的“使用帮助?”。

  4. sw2wolf
    December 30th, 2008 at 11:26 | #4

    jackyz :
    @Godwit,代码排版,可以参看顶部菜单中的“使用帮助?”。

    不错

  5. laja
    July 2nd, 2010 at 15:11 | #5

    我昏了, gen_tcp:controlling_process 只能转移控制权一次,你的程序仍然无法实现无阻塞的接收

  1. No trackbacks yet.