`
AvinDev
  • 浏览: 113348 次
社区版块
存档分类
最新评论

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

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

引用
lib_chan_mm: protocol error:{login,"general","joe"}


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

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.


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

MM ! {login, Group, Nick},

MM ! {relay, Nick, Str},


居然有这样的代码在客户端。修正bug很简单,在 lib_chan_mm.erl 有这个函数:
send(Pid, Term)       -> Pid ! {send, Term}.

替换一下,将
MM ! {login, Group, Nick},

这类,换成
lib_chan_mm:send(MM, {login, Group, Nick}),


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


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

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




lib_chan_mm:send(C, ack),

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



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

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


晕了,再次将

{MM, ack} ->

{MM,{msg,From,Pid,Str}} ->


改为

{chan, MM, ack} ->

{chan, MM,{msg,From,Pid,Str}} ->


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

引用
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"}}


引用
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}


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


顺便附上修改过后的代码吧,等此书正式release了,估计代码也改过来了吧。

分享到:
评论

相关推荐

    socket网络编程实例代码_socket服务端编程实例代码_

    本实例主要探讨了如何使用C语言实现Socket服务端和客户端的编程,通过`server.c.txt`和`client.c.txt`两个文件来展示具体的操作流程。 首先,我们来看服务端的编程。在`server.c.txt`中,服务端主要完成了以下步骤...

    Java socket编程实例代码(Blog配套代码)

    本实例代码是为了配合博客文章,提供一个简单的Java Socket聊天室的实现,帮助读者更好地理解和应用Socket编程。 在Java Socket编程中,主要有两个核心概念:服务器端(Server)和客户端(Client)。服务器端通过...

    Socket 网络通信实例代码

    本文将深入探讨Socket通信的基本概念、步骤,并通过一个实例代码来帮助初学者理解如何使用C++进行Socket编程。 首先,Socket是网络上的两个进程间通信的一种端点,它提供了一种在不同主机间交换数据的机制。在C++中...

    vc2010 socket 教程及实例程序代码

    在这个"vc2010 socket 教程及实例程序代码"中,我们聚焦于使用Visual C++ 2010(简称vc2010)进行Socket编程,特别是客户端方面的实践。Socket接口在Windows环境下通常通过winsock库来实现,它为应用程序提供了标准...

    C# Socket 多人聊天实例代码

    C# Socket 多人聊天实例代码,Vs2005已经测试通过.

    socket通信实例客户端代码

    本实例是关于C++环境下使用Winsock库进行Socket通信的客户端代码,适用于Visual Studio 2010开发环境。这个项目包含了连接服务器、断开连接以及发送消息等基本功能,对于学习和理解Socket通信机制具有很高的实践价值...

    IOS-Socket通信实例代码

    本实例代码“IOS-Socket通信实例代码”提供了在iOS平台上使用Socket进行通信的具体实现,适用于创建例如智能家居控制等应用场景。 Socket通信的核心原理是基于TCP/IP协议栈,它在应用层与传输层之间提供了一个接口...

    CSharp-Socket-.rar_C#实例 socket_SOCKET编程实例_c# socket 实例_c# socket

    在标题中提到的"C#实例 socket SOCKET编程实例_c# socket 实例_c# socket",就是指使用C#语言实现Socket通信的各种示例代码。 1. **基本概念**: - **Socket类型**:C#中的Socket类有两种主要类型,即TCP...

    MFC socket 服务器端编程实例

    MFC socket 服务器端编程实例MFC socket 服务器端编程实例MFC socket 服务器端编程实例MFC socket 服务器端编程实例MFC socket 服务器端编程实例MFC socket 服务器端编程实例

    C#中Socket多线程编程实例

    C#中Socket多线程编程实例.pdf

    SuperSocket实例代码

    本实例代码将展示如何使用SuperSocket来构建一个基本的服务端应用程序。 在传统的Socket编程中,我们通常会将所有逻辑封装在一个大类中,这可能违背了面向对象设计(OOD)的原则,比如单一职责原则、开闭原则等。...

    Socket高级编程实例

    在"20_Socket高级编程实例.wmv"这个视频教程中,可能会详细展示这些步骤,并给出实际代码示例,帮助初学者更好地理解和应用Socket编程。可能涵盖的主题包括多线程处理多个客户端连接、异步I/O模型(如epoll)、错误...

    Socket编程实例(源代码、协议、实例)

    这个压缩包包含的资源是Socket编程的学习资料,包括源代码、协议文档以及编译后的客户端和服务器端程序,非常适合初学者深入理解和实践。 首先,我们来看"Socket"这一核心概念。Socket在英文中的含义是插座,但在...

    Socket编程实例

    在这个C#的实例中,我们探讨了如何使用Socket类创建一个简单的聊天通信程序,包括客户端和服务端的实现。以下是对这个主题的详细解释: 一、Socket基础 Socket是网络通信的一种接口,它提供了一种标准的方法来通过...

    Socket网络编程实例代码

    在本实例中,我们将重点讨论如何使用C#语言实现Socket编程,特别是TCP协议下的客户端和服务器端的通信。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP保证了...

    c# socket编程实例

    ### C# Socket编程实例详解 #### 一、引言 Socket 编程是网络通信的基础技术之一,在 C# 中可以通过 System.Net.Sockets 命名空间提供的类来实现。本篇文章将通过一个具体的 C# Socket 编程实例来详细介绍 Socket ...

    Socket通信实例代码

    a. 建立一个套接字 b. 绑定本机的IP和端口 c. 如果是TCP,因为是面向连接的,所以要利用ListenO()方法来监听网络上是否有人给自己发东西;如果是UDP,因为是无连接的,所以来者不拒。 ...d....而UDP,则不需要accept, ...

Global site tag (gtag.js) - Google Analytics