修正Socket Base Distribution一节实例代码的Bug

拿到了Programming Erlang的电子书,研究一下Potian先前跟俺说的“Socket Base Distribution”部分代码,结果发现chat_client.erl(对应书上的Chapter 11 IRC Lite),运行出错,提示

[quote]lib_chan_mm: protocol error:{login,"general","joe"}[/quote]

查看lib_chan_mm.erl,可见如下代码:

[code]loop1(Socket, Pid, Trace) ->
receive
{tcp, Socket, Bin} ->
Term = binary_to_term(Bin),
trace_it(Trace,{socketReceived, Term}),
Pid ! {chan, self(), Term},
loop1(Socket, Pid, Trace);
{tcp_closed, Socket} ->
trace_it(Trace, socketClosed),
Pid ! {chan_closed, self()};
{'EXIT', Pid, Why} ->
trace_it(Trace,{controllingProcessExit, Why}),
gen_tcp:close(Socket);
{setController, Pid1} ->
trace_it(Trace, {changedController, Pid}),
loop1(Socket, Pid1, Trace);
{trace, Trace1} ->
trace_it(Trace, {setTrace, Trace1}),
loop1(Socket, Pid, Trace1);
close ->
trace_it(Trace, closedByClient),
gen_tcp:close(Socket);
{send, Term} ->
trace_it(Trace, {sendingMessage, Term}),
gen_tcp:send(Socket, term_to_binary(Term)),
loop1(Socket, Pid, Trace);
UUg ->
io:format("lib_chan_mm: protocol error:~p~n",[UUg]),
loop1(Socket, Pid, Trace)
end.[/code]

可见此Middle Man进程接收到“{login,"general","joe"}”这样的原始数据了,估计是客户端代码直接发过去的,果然如此:

[code]MM ! {login, Group, Nick},

MM ! {relay, Nick, Str},[/code]

居然有这样的代码在客户端。修正bug很简单,在 lib_chan_mm.erl 有这个函数:
[code]send(Pid, Term) -> Pid ! {send, Term}.[/code]
替换一下,将
[code]MM ! {login, Group, Nick},[/code]
这类,换成
[code]lib_chan_mm:send(MM, {login, Group, Nick}),[/code]

客户端可以了,但接着发现,服务器端出问题了 :?
[quote]2> lib_chan_mm: protocol error:ack
2> lib_chan_mm: protocol error:{msg,"joe",<0.35.0>,"I'm starting the group"}[/quote]

检查chat_server.erl,最后将问题定位在chat_group.erl,修改
[code]C ! ack,

foreach(fun({Pid,_}) -> Pid ! {msg, Nick, C, Str} end, L),[/code]



[code]lib_chan_mm:send(C, ack),

foreach(fun({Pid,_}) -> lib_chan_mm:send(Pid, {msg, Nick, C, Str}) end, L),[/code]


再试,sigh,客户端又出问题

[code]2> chat_client login unexpected:{chan,
<0.40.0>,
{msg,
"joe",
<0.45.0>,
"I'm starting the group"}}[/code]

晕了,再次将

[code]{MM, ack} ->

{MM,{msg,From,Pid,Str}} ->[/code]

改为

[code]{chan, MM, ack} ->

{chan, MM,{msg,From,Pid,Str}} ->[/code]

重新编译和启动服务器和客户端,终于可以了 :lol:

[quote]3> chat_server:start().
lib_chan starting:"chat.conf"
ConfigData=[{port,2223},
{service,chat,
password,
"AsDT67aQ",
mfa,
mod_chat_controller,
start,
[]}]
true
4> mod_chat_controller off we go ...<0.45.0>
4> group controller received Msg={chan_closed,<0.45.0>}
4> server error should die with exit(normal) was:{mm_closed,<0.45.0>}
4> mod_chat_controller off we go ...<0.48.0>
4> group controller received Msg={chan,<0.48.0>,{relay,"joe"," haha"}}
4> group controller received Msg={chan,<0.48.0>,close}
4> mod_chat_controller off we go ...<0.51.0>
4> mod_chat_controller off we go ...<0.55.0>
4> mod_chat_controller off we go ...<0.53.0>
4> mod_chat_controller off we go ...<0.57.0>
4> group controller received Msg={chan,<0.51.0>,{relay,"joe"," welcome all"}}[/quote]

[quote]2> chat_client:test().
<0.39.0>
3> chat_client login unexpected:{'EXIT',<0.52.0>,connectorFinished}
3> chat_client login unexpected:{'EXIT',<0.48.0>,connectorFinished}
3> chat_client login unexpected:{'EXIT',<0.50.0>,connectorFinished}
3> chat_client login unexpected:{'EXIT',<0.46.0>,connectorFinished}[/quote]

在弹出的窗口里面自由聊天吧。至于为什么客户端会输出“chat_client login unexpected:{'EXIT',<0.46.0>,connectorFinished}”这样的信息,是因为try_to_connect函数里面,exit(connectorFinished)执行后会发送一个'EXIT'事件给client进程。


顺便附上修改过后的代码吧,等此书正式release了,估计代码也改过来了吧。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值