拿到了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了,估计代码也改过来了吧。
分享到:
相关推荐
本实例主要探讨了如何使用C语言实现Socket服务端和客户端的编程,通过`server.c.txt`和`client.c.txt`两个文件来展示具体的操作流程。 首先,我们来看服务端的编程。在`server.c.txt`中,服务端主要完成了以下步骤...
本实例代码是为了配合博客文章,提供一个简单的Java Socket聊天室的实现,帮助读者更好地理解和应用Socket编程。 在Java Socket编程中,主要有两个核心概念:服务器端(Server)和客户端(Client)。服务器端通过...
本文将深入探讨Socket通信的基本概念、步骤,并通过一个实例代码来帮助初学者理解如何使用C++进行Socket编程。 首先,Socket是网络上的两个进程间通信的一种端点,它提供了一种在不同主机间交换数据的机制。在C++中...
在这个"vc2010 socket 教程及实例程序代码"中,我们聚焦于使用Visual C++ 2010(简称vc2010)进行Socket编程,特别是客户端方面的实践。Socket接口在Windows环境下通常通过winsock库来实现,它为应用程序提供了标准...
C# Socket 多人聊天实例代码,Vs2005已经测试通过.
本实例是关于C++环境下使用Winsock库进行Socket通信的客户端代码,适用于Visual Studio 2010开发环境。这个项目包含了连接服务器、断开连接以及发送消息等基本功能,对于学习和理解Socket通信机制具有很高的实践价值...
本实例代码“IOS-Socket通信实例代码”提供了在iOS平台上使用Socket进行通信的具体实现,适用于创建例如智能家居控制等应用场景。 Socket通信的核心原理是基于TCP/IP协议栈,它在应用层与传输层之间提供了一个接口...
在标题中提到的"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 服务器端编程实例
C#中Socket多线程编程实例.pdf
本实例代码将展示如何使用SuperSocket来构建一个基本的服务端应用程序。 在传统的Socket编程中,我们通常会将所有逻辑封装在一个大类中,这可能违背了面向对象设计(OOD)的原则,比如单一职责原则、开闭原则等。...
在"20_Socket高级编程实例.wmv"这个视频教程中,可能会详细展示这些步骤,并给出实际代码示例,帮助初学者更好地理解和应用Socket编程。可能涵盖的主题包括多线程处理多个客户端连接、异步I/O模型(如epoll)、错误...
这个压缩包包含的资源是Socket编程的学习资料,包括源代码、协议文档以及编译后的客户端和服务器端程序,非常适合初学者深入理解和实践。 首先,我们来看"Socket"这一核心概念。Socket在英文中的含义是插座,但在...
在这个C#的实例中,我们探讨了如何使用Socket类创建一个简单的聊天通信程序,包括客户端和服务端的实现。以下是对这个主题的详细解释: 一、Socket基础 Socket是网络通信的一种接口,它提供了一种标准的方法来通过...
在本实例中,我们将重点讨论如何使用C#语言实现Socket编程,特别是TCP协议下的客户端和服务器端的通信。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP保证了...
### C# Socket编程实例详解 #### 一、引言 Socket 编程是网络通信的基础技术之一,在 C# 中可以通过 System.Net.Sockets 命名空间提供的类来实现。本篇文章将通过一个具体的 C# Socket 编程实例来详细介绍 Socket ...
a. 建立一个套接字 b. 绑定本机的IP和端口 c. 如果是TCP,因为是面向连接的,所以要利用ListenO()方法来监听网络上是否有人给自己发东西;如果是UDP,因为是无连接的,所以来者不拒。 ...d....而UDP,则不需要accept, ...