﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-教父的告白-随笔分类-erlang</title><link>http://www.cppblog.com/keigoliye/category/11700.html</link><description>一切都是纸老虎</description><language>zh-cn</language><lastBuildDate>Wed, 09 Dec 2009 13:29:16 GMT</lastBuildDate><pubDate>Wed, 09 Dec 2009 13:29:16 GMT</pubDate><ttl>60</ttl><item><title>erlang群2009-12-7日关于用其他语言实现erlang模式的聊天记录</title><link>http://www.cppblog.com/keigoliye/archive/2009/12/07/102764.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Mon, 07 Dec 2009 15:49:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/12/07/102764.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/102764.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/12/07/102764.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/102764.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/102764.html</trackback:ping><description><![CDATA[2009-12-7 22:19:36 LinkTalk.NET(909327571)<br>暗夜教父， 你说的6万连接，每个连接每秒发1K包吗？<br><br>2009-12-7 22:19:49 暗夜教父(199033)<br>en <br><br>2009-12-7 22:19:49 jack(357794482)<br>就是后面函数执行完成之后的结果给前面的原子吗 <br><br>2009-12-7 22:20:54 LinkTalk.NET(909327571)<br>机器配置如何？还有6万个客户端如何模拟的？<br><br>2009-12-7 22:21:41 暗夜教父(199033)<br>机器是AMD 双核 3200+<br><br>2009-12-7 22:21:50 LinkTalk.NET(909327571)<br>另外就是每个连接上的时间间隔为1秒，没有延迟吗？<br><br>2009-12-7 22:22:12 暗夜教父(199033)<br>内存是4G，操作系统ubuntu 9.10<br><br>2009-12-7 22:22:53 暗夜教父(199033)<br>我人为的没做这种延迟<br><br>2009-12-7 22:23:04 暗夜教父(199033)<br>服务器和客户端都是这个配置<br><br>2009-12-7 22:23:16 暗夜教父(199033)<br>客户端是用erlang模拟并发<br><br>2009-12-7 22:23:39 暗夜教父(199033)<br>不过创建6W个连接花费了一定的时间<br><br>2009-12-7 22:24:09 暗夜教父(199033)<br>对哦，这样就不是6万个一起并发出来的<br><br>2009-12-7 22:24:09 LinkTalk.NET(909327571)<br>大概多久？<br><br>2009-12-7 22:24:19 暗夜教父(199033)<br>没统计时间<br><br>2009-12-7 22:24:42 暗夜教父(199033)<br>这里存在问题了<br><br>2009-12-7 22:25:27 暗夜教父(199033)<br>其实并发应该是 连接数 / 创建并发的时间<br><br>2009-12-7 22:25:27 LinkTalk.NET(909327571)<br>什么问题？<br><br>2009-12-7 22:25:49 LinkTalk.NET(909327571)<br>这个无所谓<br><br>2009-12-7 22:26:08 LinkTalk.NET(909327571)<br>只要你全部连接创建好后一直保持住就可以了<br><br>2009-12-7 22:26:23 暗夜教父(199033)<br>一直保持也不是6万同时<br><br>2009-12-7 22:26:32 暗夜教父(199033)<br>创建连接有时差<br><br>2009-12-7 22:26:35 LinkTalk.NET(909327571)<br>6万个如果能够1k/s的保持48小时的话，非常牛逼了<br><br>2009-12-7 22:26:38 暗夜教父(199033)<br>那么发生数据也有时差<br><br>2009-12-7 22:27:53 LinkTalk.NET(909327571)<br>你通过什么方式做到间隔一秒发一次数据的？<br><br>2009-12-7 22:28:32 LinkTalk.NET(909327571)<br>sleep吗？<br><br>2009-12-7 22:29:19 LinkTalk.NET(909327571)<br>你有没有看一下网卡的带宽消耗<br><br>2009-12-7 22:29:37 LinkTalk.NET(909327571)<br>按道理应该1k * 6万 = 60M/s<br><br>2009-12-7 22:30:12 LinkTalk.NET(909327571)<br>如果达到60M以上基本算是真正的稳定的实现了6万并发<br><br>2009-12-7 22:30:34 暗夜教父(199033)<br>client那边是我同事写的<br><br>2009-12-7 22:30:39 暗夜教父(199033)<br>我不知道是不是sleep<br><br>2009-12-7 22:30:52 暗夜教父(199033)<br>带宽消耗我还也真没看<br><br>2009-12-7 22:30:53 LinkTalk.NET(909327571)<br>erlang里面好像也就只有sleep了<br><br>2009-12-7 22:31:06 暗夜教父(199033)<br>我估计不是<br><br>2009-12-7 22:31:52 LinkTalk.NET(909327571)<br>另外我怀疑当并发高了以后，sleep会不准，真正的间隔肯定会大于sleep的时间<br><br>2009-12-7 22:32:50 暗夜教父(199033)<br>恩，确实有待验证<br><br>2009-12-7 22:33:04 暗夜教父(199033)<br>不过只有用应用来验证了<br><br>2009-12-7 22:33:14 暗夜教父(199033)<br>等项目上线了，看看实际情况<br><br>2009-12-7 22:33:17 LinkTalk.NET(909327571)<br>嗯，呵呵<br><br>2009-12-7 22:33:24 LinkTalk.NET(909327571)<br>你们这个用在什么项目上马？<br><br>2009-12-7 22:33:27 LinkTalk.NET(909327571)<br>上面<br><br>2009-12-7 22:33:30 LinkTalk.NET(909327571)<br>游戏吗？<br><br>2009-12-7 22:33:31 暗夜教父(199033)<br>恩，游戏的<br><br>2009-12-7 22:34:48 LinkTalk.NET(909327571)<br>[表情]<br><br>2009-12-7 22:34:59 暗夜教父(199033)<br>不过风险也很大<br><br>2009-12-7 22:35:15 LinkTalk.NET(909327571)<br>为什么？<br><br>2009-12-7 22:35:24 暗夜教父(199033)<br>没做过<br><br>2009-12-7 22:35:28 暗夜教父(199033)<br>没有成熟项目的经验<br><br>2009-12-7 22:35:29 LinkTalk.NET(909327571)<br>呵呵<br><br>2009-12-7 22:35:32 暗夜教父(199033)<br>什么都有可能发生<br><br>2009-12-7 22:35:45 LinkTalk.NET(909327571)<br>传统的游戏服务器，单台到两三万并发已经很牛X了<br><br>2009-12-7 22:35:50 暗夜教父(199033)<br>未知因素太多<br><br>2009-12-7 22:36:00 暗夜教父(199033)<br>我估计6W还能上<br><br>2009-12-7 22:36:00 LinkTalk.NET(909327571)<br>而且硬件还不差的情况下<br><br>2009-12-7 22:36:11 LinkTalk.NET(909327571)<br>游戏的数据通信量比较大<br><br>2009-12-7 22:36:22 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 22:36:30 暗夜教父(199033)<br>没过6W是因为客户端的端口基本上没了<br><br>2009-12-7 22:36:45 LinkTalk.NET(909327571)<br>这个不会啊<br><br>2009-12-7 22:36:51 LinkTalk.NET(909327571)<br>客户端端口没有关系的<br><br>2009-12-7 22:36:55 暗夜教父(199033)<br>有吧<br><br>2009-12-7 22:36:59 LinkTalk.NET(909327571)<br>因为IP不一样<br><br>2009-12-7 22:37:11 暗夜教父(199033)<br>不是。我测试的时候<br><br>2009-12-7 22:37:15 LinkTalk.NET(909327571)<br>同一个IP有65535个端口的限制<br><br>2009-12-7 22:37:18 暗夜教父(199033)<br>6万个连接从一台机器来的<br><br>2009-12-7 22:37:18 LinkTalk.NET(909327571)<br>哦，了解<br><br>2009-12-7 22:37:23 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 22:37:54 david(258667581)<br>服务器端只监听一个端口 应该不会有端口数限制吧？<br><br>2009-12-7 22:38:24 LinkTalk.NET(909327571)<br>服务器端不会<br><br>2009-12-7 22:38:50 david(258667581)<br>做游戏的话 不是都雍和宫服务器吗<br><br>2009-12-7 22:38:55 david(258667581)<br>都做的服务器吗<br><br>2009-12-7 22:39:24 暗夜教父(199033)<br>。。。<br><br>2009-12-7 22:39:32 暗夜教父(199033)<br>我是做测试<br><br>2009-12-7 22:39:36 david(258667581)<br>另外 如果端口socket属性设置reuse为true 是否可以超过6W端口<br><br>2009-12-7 22:39:48 LinkTalk.NET(909327571)<br>不会<br><br>2009-12-7 22:39:53 暗夜教父(199033)<br>服务器端是一台机器，客户端也是一台机器<br><br>2009-12-7 22:39:56 LinkTalk.NET(909327571)<br>那个是针对不同的protocol<br><br>2009-12-7 22:40:02 暗夜教父(199033)<br>客户端发起6W个连接<br><br>2009-12-7 22:40:19 暗夜教父(199033)<br>就要占用6W多个端口<br><br>2009-12-7 22:40:18 david(258667581)<br>不同的protocol是什么意思<br><br>2009-12-7 22:40:35 LinkTalk.NET(909327571)<br>tcp 和 udp 可以reuse同一个port<br><br>2009-12-7 22:41:09 LinkTalk.NET(909327571)<br>erlang其实我只是大概的了解<br><br>2009-12-7 22:41:22 LinkTalk.NET(909327571)<br>我打算用C#和Java模拟erlang<br><br>2009-12-7 22:41:26 david(258667581)<br>程序a试用端口2000 tcp连 然后 程序b用2000端口udp再连接另外一个程序？<br><br>2009-12-7 22:41:36 david(258667581)<br>模拟？<br><br>2009-12-7 22:41:40 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 22:41:47 LinkTalk.NET(909327571)<br>我已经用C#实现了<br><br>2009-12-7 22:41:47 david(258667581)<br>怎么模拟？<br><br>2009-12-7 22:41:59 LinkTalk.NET(909327571)<br>就是Actor模式<br><br>2009-12-7 22:42:07 LinkTalk.NET(909327571)<br>自己实现消息的调度<br><br>2009-12-7 22:42:15 LinkTalk.NET(909327571)<br>还有实现异步编程接口<br><br>2009-12-7 22:42:41 david(258667581)<br>actor模式是什么意思<br><br>2009-12-7 22:42:59 LinkTalk.NET(909327571)<br>一种软件设计模式<br><br>2009-12-7 22:43:16 LinkTalk.NET(909327571)<br>erlang/scala等并发平台都是actor模式<br><br>2009-12-7 22:44:06 david(258667581)<br>不懂<br><br>2009-12-7 22:44:25 david(258667581)<br>为什么要用c#模拟？<br><br>2009-12-7 22:44:33 LinkTalk.NET(909327571)<br>因为我熟悉C#<br><br>2009-12-7 22:44:39 LinkTalk.NET(909327571)<br>也打算用java模拟<br><br>2009-12-7 22:45:01 LinkTalk.NET(909327571)<br>同时也因为C#/Java有大量的开发人员和丰富的第三方扩展<br><br>2009-12-7 22:45:25 LinkTalk.NET(909327571)<br>同时也有很爽的IDE<br><br>2009-12-7 22:45:26 LinkTalk.NET(909327571)<br>：）<br><br>2009-12-7 22:45:42 david(258667581)<br>是 但是感觉如果你是要测性能的话 c#的性能可能跟不上erlang啊<br><br>2009-12-7 22:45:49 david(258667581)<br>用c的都会好些<br><br>2009-12-7 22:46:01 LinkTalk.NET(909327571)<br>其实erlang语言本身性能不见得高，因为是脚本语言<br><br>2009-12-7 22:46:15 LinkTalk.NET(909327571)<br>高并发是因为纯消息传递，可以有效的避免死锁<br><br>2009-12-7 22:46:27 LinkTalk.NET(909327571)<br>传统语言比如c/c++要避免死锁比较难<br><br>2009-12-7 22:46:49 LinkTalk.NET(909327571)<br>给大家看老外的一个测试数据<br><br>2009-12-7 22:46:57 LinkTalk.NET(909327571)<br>erlang其实算是执行效率相对比较差的<br><br>2009-12-7 22:47:20 david(258667581)<br>哪里 erlang的性能应该是可以跟c叫板的<br><br>2009-12-7 22:48:04 LinkTalk.NET(909327571)<br>http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&amp;lang=csharp&amp;lang2=hipe&amp;box=1<br><br>2009-12-7 22:48:16 LinkTalk.NET(909327571)<br>这个里面有很多语言的性能测试比较<br><br>2009-12-7 22:48:23 LinkTalk.NET(909327571)<br>erlang算是比较差的<br><br>2009-12-7 22:49:02 LinkTalk.NET(909327571)<br>传统语言达不到高并发是因为无法有效的避免死锁，还有cpu调度做得不好<br><br>2009-12-7 22:50:17 暗夜教父(199033)<br>恩，C如果使用erlang的模式<br><br>2009-12-7 22:50:26 暗夜教父(199033)<br>绝对不会输<br><br>2009-12-7 22:50:29 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 22:50:37 LinkTalk.NET(909327571)<br>erlang本身就是C写的<br><br>2009-12-7 22:50:41 暗夜教父(199033)<br>恩<br><br>2009-12-7 22:50:54 LinkTalk.NET(909327571)<br>我记得国内好像有个牛人在研究用C++模拟erlang<br><br>2009-12-7 22:51:00 LinkTalk.NET(909327571)<br>好像是盛大的一个架构师<br><br>2009-12-7 22:51:13 暗夜教父(199033)<br>貌似现在做linux下做服务器端得，C比C++多了<br><br>2009-12-7 22:51:20 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 22:51:29 LinkTalk.NET(909327571)<br>linux下c多<br><br>2009-12-7 22:51:36 暗夜教父(199033)<br>我记得好像云风把大话西游的服务器端改成C了<br><br>2009-12-7 22:52:28 小生啊牙(86753957)<br>51.com的服务器就是用C++模拟erlang的<br><br>2009-12-7 22:52:50 小生啊牙(86753957)<br>使用协程<br><br>2009-12-7 22:53:59 LinkTalk.NET(909327571)<br>嗯，协程可以在传统的面向过程的线程上模拟异步操作<br><br>2009-12-7 22:55:05 LinkTalk.NET(909327571)<br>其实高并发只是一种设计模式<br><br>2009-12-7 22:55:19 LinkTalk.NET(909327571)<br>erlang把这个设计模式固化并强制到语法里了<br><br>2009-12-7 22:56:22 LinkTalk.NET(909327571)<br>C#2.0开始有个新的特性，叫iterator，通过yield关键字来实现coroutine（协程）<br><br>2009-12-7 22:56:39 LinkTalk.NET(909327571)<br>并且在语法上也可以用连贯的形式来实现异步的操作<br><br>2009-12-7 22:56:49 LinkTalk.NET(909327571)<br>和erlang的形式类似<br><br>2009-12-7 22:57:10 LinkTalk.NET(909327571)<br>java里面目前只有anonymous class可以实现异步调用<br><br>2009-12-7 22:57:44 LinkTalk.NET(909327571)<br>但是那个语法写起来有些牵强，花括号会越嵌越深<br><br>2009-12-7 22:59:19 LinkTalk.NET(909327571)<br>我用C#实现的actor模式也可以处理每分钟大概200万条消息（在PC上）<br><br>2009-12-7 22:59:24 LinkTalk.NET(909327571)<br>AMD双核<br><br>2009-12-7 23:00:28 LinkTalk.NET(909327571)<br>也测试过HTTP 请求，大概可以达到1万多并发，不过是6秒一个请求（sleep6秒，实际会延迟到10秒以上），cpu占用40-60<br><br>2009-12-7 23:01:54 LinkTalk.NET(909327571)<br>每分钟200万消息是最简单的ping/pong测试<br><br>2009-12-7 23:06:12 david(258667581)<br>以前没听说过 协程 呵呵<br><br>2009-12-7 23:06:33 LinkTalk.NET(909327571)<br>是否有协程无所谓的<br><br>2009-12-7 23:07:14 LinkTalk.NET(909327571)<br>关键是纯消息传递（避免死锁）还有线程合理有效的调度（实现高效的异步处理）<br><br>2009-12-7 23:07:35 david(258667581)<br>恩 关键是避开锁<br><br>2009-12-7 23:08:04 LinkTalk.NET(909327571)<br>并最好再能够在语法上将异步操作用顺序化的代码来表示<br><br>2009-12-7 23:08:22 LinkTalk.NET(909327571)<br>实在不行也无所谓，可以用event handler的方式<br><br>2009-12-7 23:08:48 david(258667581)<br>能否举一个异步操作的具体应用场景？<br><br>2009-12-7 23:09:08 LinkTalk.NET(909327571)<br>很多都是异步操作（那样IO才可以做到高效）<br><br>2009-12-7 23:09:19 LinkTalk.NET(909327571)<br>比如epoll和windows的iocp<br><br>2009-12-7 23:09:22 LinkTalk.NET(909327571)<br>都是异步的<br><br>2009-12-7 23:09:44 LinkTalk.NET(909327571)<br>简单的原理就是调用函数递交或注册一个IO请求到系统内核<br><br>2009-12-7 23:09:45 david(258667581)<br>是不是都是底层的<br><br>2009-12-7 23:09:55 LinkTalk.NET(909327571)<br>然后不需要阻塞，立即返回<br><br>2009-12-7 23:10:17 LinkTalk.NET(909327571)<br>系统IO内核收到数据或相关的事件会触发当初注册的回调函数<br><br>2009-12-7 23:10:59 LinkTalk.NET(909327571)<br>调用请求 和 数据返回或事件触发 不在同一个操作系统线程上完成，就称为异步<br><br>2009-12-7 23:11:13 LinkTalk.NET(909327571)<br>异步的IO才比较高效<br><br>2009-12-7 23:11:37 LinkTalk.NET(909327571)<br>操作系统的线程数有限制<br><br>2009-12-7 23:11:42 david(258667581)<br>这些都不难 无论是java和c#还是c，都已经有专门的api支撑了<br><br>2009-12-7 23:11:51 david(258667581)<br>关键是业务上的操作 <br><br>2009-12-7 23:11:55 LinkTalk.NET(909327571)<br>一般上了千以后，线程的效率就比较差了<br><br>2009-12-7 23:11:58 david(258667581)<br>锁的都是业务<br><br>2009-12-7 23:12:02 LinkTalk.NET(909327571)<br>而且很耗cpu和内存<br><br>2009-12-7 23:12:23 LinkTalk.NET(909327571)<br>所以要通过合理的调度和异步操作来分享宝贵的操作系统线程<br><br>2009-12-7 23:12:51 LinkTalk.NET(909327571)<br>严格遵守actor模式可以有效的避免死锁 <br><br>2009-12-7 23:13:04 david(258667581)<br>[表情]<br><br>2009-12-7 23:14:34 LinkTalk.NET(909327571)<br>我也在摸索和尝试，erlang的消息调度和分布式支持是目前最好的<br><br>2009-12-7 23:14:49 LinkTalk.NET(909327571)<br>scala也不错，twitter就放弃erlang转向scala<br><br>2009-12-7 23:15:00 LinkTalk.NET(909327571)<br>但是scala在分布式支持方面不及erlang<br><br>2009-12-7 23:15:30 LinkTalk.NET(909327571)<br>但是scala有最大的好处就是基于JVM，可以利用java的各种好处<br><br>2009-12-7 23:15:33 david(258667581)<br>分布式以后是趋势 所以感觉erlang的生命力应该还是很强的<br><br>2009-12-7 23:15:44 LinkTalk.NET(909327571)<br>嗯，分布式其实其他语言也可以做的<br><br>2009-12-7 23:16:05 LinkTalk.NET(909327571)<br>只是erlang已经做了十几年了<br><br>2009-12-7 23:16:19 LinkTalk.NET(909327571)<br>其他语言也肯定会逐渐支持的<br><br>2009-12-7 23:16:25 david(258667581)<br>恩<br><br>2009-12-7 23:16:43 LinkTalk.NET(909327571)<br>但是我个人比较觉得遗憾的是erlang的语法和编程模式<br><br>2009-12-7 23:17:08 LinkTalk.NET(909327571)<br>如果erlang代码上到一定的量以后维护和调试就相当麻烦了<br><br>2009-12-7 23:17:11 david(258667581)<br>语法习惯了就好 关键是对于结构的支持<br><br>2009-12-7 23:17:17 david(258667581)<br>可读性太差<br><br>2009-12-7 23:17:31 LinkTalk.NET(909327571)<br>嗯，数据结构表现力也不够丰富<br><br>2009-12-7 23:17:35 LinkTalk.NET(909327571)<br>都是tuple<br><br>2009-12-7 23:17:43 LinkTalk.NET(909327571)<br>眼睛要看花了<br><br>2009-12-7 23:19:09 david(258667581)<br>开发环境也没跟上 没有很好的IDE<br><br>2009-12-7 23:19:16 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 23:19:37 LinkTalk.NET(909327571)<br>脚本语言重构起来就相当麻烦了<br><br>2009-12-7 23:19:57 T.t.T!Ck.￠#(121787333)<br>有一个老外也用C#来模拟erlang的模式<br><br>2009-12-7 23:20:06 LinkTalk.NET(909327571)<br>因为无类型，无法反射元数据，没有办法自动生成文档，更难重构<br><br>2009-12-7 23:20:07 Lenn(28663)<br>ERLANG跟Java一样是编译态语言，怎么成脚本语言了<br><br>2009-12-7 23:20:22 LinkTalk.NET(909327571)<br>erlang严格来讲是脚本<br><br>2009-12-7 23:20:31 LinkTalk.NET(909327571)<br>弱类型的基本都是脚本<br><br>2009-12-7 23:20:44 LinkTalk.NET(909327571)<br>包括php也号称支持编译<br><br>2009-12-7 23:20:47 LinkTalk.NET(909327571)<br>其实还是脚本<br><br>2009-12-7 23:21:16 Lenn(28663)<br>bin code只有200多条指令，属于典型的中间太语言，效率不会比Java差多少<br><br>2009-12-7 23:21:34 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 23:21:48 LinkTalk.NET(909327571)<br>我觉得任何东西都有得必有失<br><br>2009-12-7 23:21:57 LinkTalk.NET(909327571)<br>一方面太强了，比如有其他的缺陷<br><br>2009-12-7 23:22:06 LinkTalk.NET(909327571)<br>就看自己的喜好和具体的应用场景了<br><br>2009-12-7 23:22:08 Lenn(28663)<br>图形太弱<br><br>2009-12-7 23:22:47 Lenn(28663)<br>调试起来最爽，业务想对了基本不会编程从出错<br><br>2009-12-7 23:23:16 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 23:24:26 Lenn(28663)<br>我们就是一个案例，用ＪＡＶＡ做的东西，现在还不停改代码，Ｅｒｌａｎｇ那一块，要改也只是几行一会的事情<br><br>2009-12-7 23:25:17 jack(357794482)<br>其实这种事情要看你对语言的处理能力 <br><br>2009-12-7 23:25:20 LinkTalk.NET(909327571)<br>嗯<br><br>2009-12-7 23:25:35 LinkTalk.NET(909327571)<br>google的首席架构师是搞java的<br><br>2009-12-7 23:25:41 LinkTalk.NET(909327571)<br>其实这个看具体情况的<br><br>2009-12-7 23:26:17 Lenn(28663)<br>用什么还有历史原因，比如新的facebook很多用Erlang<br><br>2009-12-7 23:26:33 Lenn(28663)<br>因为做好的东西更改语言是个大问题<br><br>2009-12-7 23:26:36 LinkTalk.NET(909327571)<br>但是更新的twitter由erlang转向了scala<br><br>2009-12-7 23:26:58 LinkTalk.NET(909327571)<br>另外erlang十几年了，到今天才红，也是有一定的原因的<br><br>2009-12-7 23:27:13 LinkTalk.NET(909327571)<br>erlang有非常突出的优势，但是也存在一些不够完美的地方<br><br>2009-12-7 23:29:04 Lenn(28663)<br>现在社区也挺活跃，业务有比较强的优势<br><br>2009-12-7 23:29:37 LinkTalk.NET(909327571)<br>嗯，是的；）<br><br>2009-12-7 23:29:57 LinkTalk.NET(909327571)<br>所以就算其他语言的开发人员也开始了解<br><br>2009-12-7 23:30:02 LinkTalk.NET(909327571)<br>学习、<br><br>2009-12-7 23:30:04 Lenn(28663)<br>图形方面却丝毫不行<br><br>2009-12-7 23:30:05 LinkTalk.NET(909327571)<br>或模拟erlang<br><br>2009-12-7 23:30:08 LinkTalk.NET(909327571)<br>嗯<br><img src ="http://www.cppblog.com/keigoliye/aggbug/102764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-12-07 23:49 <a href="http://www.cppblog.com/keigoliye/archive/2009/12/07/102764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Patch Mnesia 使用TokyoCabinet引擎突破2G存储限制</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/29/97547.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Tue, 29 Sep 2009 07:12:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/29/97547.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/97547.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/29/97547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/97547.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/97547.html</trackback:ping><description><![CDATA[<p>为啥要PATCH？</p>
<p>&nbsp;&nbsp;&nbsp; Mnesia最大的缺陷是存储限制。这不是数据库系统的错误，因为Mnesia能够控制虚拟数据的大小。主要的问题在于过时的Erlang DETS存储引擎，速度慢并且使用的32位偏移量（限制单文件大小为2GB）。 </p>
<p>思路？</p>
<p>&nbsp;&nbsp;&nbsp; 超乎想象的 mnesia 补丁包 mnesiaex 。这个东西解除了加在 mnesia 数据库系统上所有的限制(虽说上面已经提到，实际上 mnesia 代码本身没有什么真正的限制)——你现在可以用 SleepyCat/BerkeleyDB/MySQL/Amazon S3/Tokyo Cabinet/&#8230; 甚至是你自己喜欢的某种东西来当作 mnesia 的后端，就像 ets/dets 一样。而访问的接口仍保持不变——继续沿用 mnesia 的接口，一行也不用改。 DIY 这种扩展也变得相当容易，写一个 behavior 就成了。</p>
<p>实现过程</p>
<p>1：与从源代码编译的方式安装Erlang</p>
<p>tar xvf otp_src_R12B-5.tar.gz</p>
<p>cd otp_src_R12B-5</p>
<p>./configure &amp; make &amp; make install</p>
<p>注意：我的系统是RHEL 5.3，默认安装目录为/usr/local/erlang</p>
<p>2：安装Mnesiaex</p>
<p>tar xvf mnesia-4.4.7.6.tar.gz </p>
<p>cd mnesia-4.4.7.6</p>
<p>./configure --prefix=/usr/local</p>
<p>make</p>
<p>make check</p>
<p>make install</p>
<p>注意：这里一定要指定prefix，不然就装到/usr目录去了</p>
<p>3：安装Tokyo Cabinet</p>
<p>tar xvf&nbsp; tokyocabinet-1.4.10.tar.gz</p>
<p>cd tokyocabinet-1.4.10</p>
<p>./configure --prefix=/usr</p>
<p>make &amp; make install </p>
<p>3：安装tcerl</p>
<p>tar xvf tcerldrv-1.3.1e.tar.gz </p>
<p>cd tcerldrv-1.3.1e</p>
<p>./configure --prefix=/usr</p>
<p>make &amp; make install</p>
<p>tar xvf tcerl-1.3.1e.tar.gz </p>
<p>cd tcerl-1.3.1e</p>
<p>./configure --prefix=/usr/local</p>
<p>make &amp; make install</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/jimmychou/archive/2009/03/13/3988468.aspx">http://blog.csdn.net/jimmychou/archive/2009/03/13/3988468.aspx</a></p>
<img src ="http://www.cppblog.com/keigoliye/aggbug/97547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-29 15:12 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/29/97547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Erlang和SMP的一些说明</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/24/97172.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Thu, 24 Sep 2009 14:23:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/24/97172.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/97172.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/24/97172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/97172.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/97172.html</trackback:ping><description><![CDATA[<div class=entry-content>
<p><a href="http://shiningray.cn/some-facts-about-erlang-and-smp.html"><u><font color=#0000ff>http://shiningray.cn/some-facts-about-<span class=hilite1>erlang</span>-and-smp.html</font></u></a></p>
<p>原文：<a href="http://groups.google.com/group/erlang-questions/browse_thread/thread/7827f5e32681ca8e"><u><font color=#0000ff>http://groups.google.com/group/<span class=hilite1>erlang</span>-questions/browse_thread/thread/7827f5e32681ca8e</font></u></a> </p>
<p>by.Kenneth <span class=hilite1>Erlang</span>/OTP team, Ericsson<br>译：<a href="http://shiningray.cn/"><u><font color=#0000ff>ShiningRay <br></font></u></a></p>
<p>&nbsp;</p>
<p>以下是一些<span class=hilite1>Erlang</span> SMP实现的细节和与性能与伸缩性相关一些简单介绍。</p>
<p>几周之内还有有一个关于多核如何运作以及未来如何发展的更详细的介绍。我打算将一些内容放在我的报告中，将于9月27日的ICFP2008，<span class=hilite1>Erlang</span> Workshop在Victoria BC展示给大家。</p>
<p>没有SMP支持的<span class=hilite1>Erlang</span> VM只有1个运行在主处理线程中的调度器。该调度器从运行队列（run-queue）中取出可以运行的<span class=hilite1>Erlang</span>进程以及IO任务，而且因为只有一个线程访问他们所以无须锁定任何数据。</p>
<p>而带有SMP支持的<span class=hilite1>Erlang</span> VM可以有一个或多个调度器，每个运行在一个线程中。调度器从同一个公共运行队列中取出可运行的<span class=hilite1>Erlang</span>进程和IO任务。在SMP VM中所有的共享数据结构都会由锁进行保护，运行队列就是这样一个由锁保护的数据结构。</p>
<p>从OTP R12B开始，如果操作系统报告有多于1个的CPU（或者核心）VM的SMP版本会自动启动，并且根据CPU或者核心的数量启动同样数量的调度器。</p>
<p>你可以从&#8220;erl&#8221;命令打印出来的第一行看到它选择了哪些参数。例如：</p>
<pre><code>
<span class=hilite1>Erlang</span> (BEAM) emulator version 5.6.4 [source] [smp:4] [asynch-threads:0] &#8230;..
其中&#8220;[smp:4]&#8221;表示SMP VM运行了4个调度器。</code>
</pre>
<p>默认值可以用&#8220;-smp [enable|disable|auto]&#8221;来替换，auto是默认的。如果smp被启用了（-smp enable），要设置调度器的数量可以使用&#8220;+S Number&#8221;其中Number是调度器的数量（1到1024）</p>
<p>注意1：运行多于CPU或核心总数的调度器不会有任何提升。</p>
<p>注意2：在某些操作系统中一个进程可使用的CPU或者核心的数量可以被限制。例如，在Linux中，命令&#8220;taskset&#8221;就可以实现这个功能。 <span class=hilite1>Erlang</span> VM目前还只能探测CPU或者核心的总数，不会考虑&#8220;taskset&#8221;所设置的掩码。正因如此，例如可能会出现（已经出现过了）即使<span class=hilite1>Erlang</span> VM运行了4个调度器，也只使用了2个核心。OS会进行限制因为它要考虑&#8220;taskset&#8221;所设置的掩码。</p>
<p>每个<span class=hilite1>Erlang</span> VM的调度器都运行于一个OS线程上，是OS来决定线程是否执行在不同的核心上。一般来说OS会很好地处理这个问题并且会保证线程在执行期间运行于同一个核心上。</p>
<p><span class=hilite1>Erlang</span>进程会被不同的调度器运行，因为他们是从一个公共运行队列中被取出，由首先可用的调度器运行。</p>
<h3>性能和伸缩性</h3>
<p>只有一个调度器的SMP VM要比非SMP的VM稍微慢那么一点点。SMP VM内部需要用到各种锁，不过只要不存在锁的争用，那么由锁引起的开销不会非常大（就是锁争用上面需要花时间）。这也解释了为何在某些情况下，运行多个只有一个调度器的SMP VM要比包含多个调度器的单一SMP VM更加高效。当然运行多个VM要求应用可以按照多个并行任务的方式运行并且之间没有或者几乎不通讯。</p>
<p>一个程序是否能在多核上的SMP VM中良好地进行提升很大程度上取决于程序的性质，某些程序可以保持线性提升至8核甚至16核，同时其他某些程序基本不能提升，连2核都不行。实际应用中很多程序都能在主流市场的核心数上得到提升，见下文。</p>
<p>若并行的持续&#8220;通话&#8221;由每个核心一个或多个<span class=hilite1>Erlang</span>进程来表示，实际的支持大量通话的电信产品已经先现出在双核和四核处理器上不俗的伸缩性。注意，这些产品是在SMP VM和多核处理器出现很久以前按照普通的<span class=hilite1>Erlang</span>风格来写的，他们也能无须任何修改甚至不需重新编译代码就能从<span class=hilite1>Erlang</span> SMP VM中获益。</p>
<h3>SMP性能得到持续改进</h3>
<p>SMP实现正被不断改进以便能得到更好的性能和伸缩性。在每个服务发布版R12B-1,2,3,4,5&#8230;,R13B等等中，你都能发现新的优化。</p>
<h3>一些已知的瓶颈</h3>
<p>单一的常见运行队列随着CPU或核心的数量的增加会成为一个显著的瓶颈。</p>
<p>这从4核开始往上就会显现出来，不过4核仍然可以为多数应用程序提供不错的性能。我们正在从事一个每个调度器一个运行队列的解决方法作为目前最重要的改进。</p>
<p>Ets表格会引入锁。在R12B-4之前在每次对一个ets-table的访问中会用到两个锁，但是在R12B-4中meta-table的锁被优化过，可以显著减少争用（前面已经提到争用是有很大代价的）。如果很多<span class=hilite1>Erlang</span>进程访问同一个表格，就会有很多锁争用造成性能降低尤其当这些进程主要工作是访问ets-table。锁存在于表级而非记录级。注意！这也会影响到Mnesia因为Mnesia用到了很多ets-table。</p>
<h3>我们关于SMP的策略</h3>
<p>当我们开始实现SMP VM的最初，我们就确定了策略：&#8220;首先让它可以运行，然后测量，然后优化&#8221;。自从2006年五月我们发布了第一个稳定的SMP VM（R11B）以来，我们一直遵循着这个策略。</p>
<p>还有更多已知的东西可以改进，我们会按照性能的收益大小先后各个击破。</p>
<p>我们将主要的精力放在多核（大于4）上更好的连续伸缩性上。</p>
<h3>卓越典范</h3>
<p>即使SMP系统有还有一些已知的瓶颈不过已经有不错的整体性能和伸缩性，同时我相信在让程序员利用多核机器事半功倍方面，我们是一个卓越的典范。</p>
</div>
<img src ="http://www.cppblog.com/keigoliye/aggbug/97172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-24 22:23 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/24/97172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang开发建议(杂记版)</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/24/97082.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Wed, 23 Sep 2009 17:00:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/24/97082.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/97082.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/24/97082.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/97082.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/97082.html</trackback:ping><description><![CDATA[以下是在<span class="hilite1">erlang</span>项目开发中的一些记录，即包含很多通俗易懂的原则，也包含一些似是而非的建议，比较混乱，还没有积累到一个可以分门别类的地步，各位就将就看吧..
<br>:) <br><br>* 确保没有任何编译警告 <br><br>* <span class="hilite1">Erlang</span>中String采用list实现，32位系统中，其1个字符用8个字节的空间（4个保存value,
4个保存指针)。因此string速度较慢，空间占用较大 <br><br>* 在Server中，总是尽力书写尾递归(tail-recursive)的函数
<br><br>* 使用'++'时，left list会被拷贝，然后添加到right list的头部，因此最好把length较短的list放在左侧
<br><br>* 避免使用regexp，如果需要正则表达式，请使用re <br><br>*
timer模块的大部分函数实现，依赖于一个process，如果过多使用timer，会导致这个process负载过大，影响效率。 <br>&nbsp; 推荐使用<span class="hilite1">erlang</span>:send_after/3及<span class="hilite1">erlang</span>:start_timer/3 <br><br>* 避免使用list_to_atom/1，因为<span class="hilite1">erlang</span>中atom数量最大为1048576, 且不进行GC控制。因此如果持续性的调用list_to_atom/1
<br>&nbsp; 可能很容易达到系统上限，从而导致emulator terminate。请使用list_to_existing_atom/1。 <br><br>*
list内部实现为一个列表，因此length(List), 需要遍历整个list比较耗时 <br><br>*
对于不同的数据类型，使用不同的size函数：tuple_size/1, byte_size/1, bit_size/1 <br><br>* 使用binary
match来进行binary的分割，而不使用split_binary/2 <br><br>*
如果两个list都拥有很多数据，那么请不要使用'--'，而是将数据转化到ordsets，然后调用ordsets:substract/2. <br><br>*
对于binary相关操作可以进行binary优化（bin_opt_info编译选项）代码框架： <br><br>*&nbsp;&nbsp;
f(&lt;&lt;Pattern1,...,Rest/bits&gt;&gt;,...) -&gt;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... % Rest is
not used here&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f(Rest,...);&nbsp; <br>&nbsp;&nbsp;&nbsp;
f(&lt;&lt;Pattern2,...,Rest/bits&gt;&gt;,...) -&gt;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... % Rest is not
used here&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f(Rest,...);&nbsp; <br>&nbsp;&nbsp;&nbsp; ...&nbsp; <br>&nbsp;&nbsp;&nbsp; f(&lt;&lt;&gt;&gt;, ...)
-&gt;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReturnValue. <br><br>*
调用lists:flatten/1可以将list扁平化，这个操作代价很大，比'++'还要昂贵。下面这些时候我们可以避免： <br>&nbsp;&nbsp;&nbsp; 将数据发送给port时
<br>&nbsp;&nbsp;&nbsp; 调用list_bo_binary/1和iolist_to_binary前 <br><br>* 小的函数可以让您方便的找出错误的函数和代码
<br><br>* 不要在同一行出现相同的符号 <br>20&nbsp;&nbsp;&nbsp; some_fun() -&gt; <br>21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; L = [{key1, v1},
{key2, [some_record#v21, v22]}], <br>22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... <br>编译时，会提示line 21 '[' 语法错误，
因为21行有多个 '[' ，所以这个bug不能准确定位，你需要花时间去排查代码。 <br>好的做法是： <br>20 some_fun() -&gt;
<br>21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; L = [{key1, v1}, <br>22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {key2, [some_record#v21, v22]}
<br>23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ], <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... <br>这样，编译其会提示你 line 22 '['
语法错误，你很开就知道是那个地方错了。 <br><br>* 使用 CTRL ＋ \ 或 init:stop()， 可以退出<span class="hilite1">Erlang</span>， 使用CTRL ＋ G 及 CTRL + C 弹出菜单选项，可以选择是否退出<span class="hilite1">Erlang</span>。 <br>其中CTRL ＋ G可以用来连接其他的shell， CTRL ＋ C可以查看其他一些系统信息
<br>Ctrl + C abort 是野蛮的退出方式 <br><br>* use "open_port({fd,0,2}, [out])" make
<span class="hilite1">erlang</span> program write standard error to unix system
<br><br>* If you don't run experiments before you start designing a new system,
your entire system will be an experiment! <br><br>* standard data structure
desc: <br><br>Module Description <br>sets sets, i.e. a collection of unique
elements. <br>gb_sets sets, but based on a general balanced data structure
<br>gb_tree a general balanced tree <br>dict maps, also called associative
arrays <br>ets hash tables and ordered sets (trees) <br>dets on-disk hash tables
<br><br>Suggestion： <br>elments count: 0 － 100 | 100 - 10000&nbsp; |&nbsp; 10000 - <br>our
select&nbsp;&nbsp; :&nbsp; list&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ets&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; gb_tree <br><br>* 通过code:clash/0
检测代码中是否有module冲突现象（sticky) <br><br>* epmd -d -d 启动 epmd 可以查看<span class="hilite1">erlang</span> node之间的通讯 <br><br>*
将正常的逻辑代码和错误处理代码分离，发生错误时，尽管错误。由另一个错误处理模块进行处理 <br><br>* 类似于操作系统，我们的程序也可以分为kernel 和
user 两层， 对于kernel绝对不能出现错误， 对于user可以出现错误，进行恢复 <br><br>*
process顶层loop涉及的代码及函数，最好在一个module中实现 <br><br>* process 的register
name和module名称一致， 便于寻找代码 <br><br>* 每个process具有一个单一的角色，比如：supervisor 用来进行错误恢复，
work 工作者，可以出现错误， trusted worker 不会出现错误 <br><br>*
通过函数调用可以实现的功能，就不要使用sever实现（如gen_server, 及类似的loop 实现） <br><br>*
给消息加一个tag，在发生错误的时候，可以定位到消息，同时也有利于程序的稳健 <br><br>*
在消息循环中，对于unknown的消息，请调用lib:flush_receive/0 将其清除，减轻process msg queue的长度 <br><br>*
server中总是书写尾递归的循环 <br><br>* 尽量使用record， 而不是原始的tuple来表现数据结构， 在使用record时，使用select
match： <br>#person{name = Name, age = Age} = Person <br><br>*
对于返回值，最好也添加一个tag，用来说明返回值类型，或者执行成功与否 <br><br>* 尽可能少的使用catch和try，在<span class="hilite1">erlang</span>程序中，不推荐主动捕获异常。只有当我们的逻辑特别复杂，我们可以使用throw来返回数据，使用catch来获取返回值。
<br><br>* 当然程序与外界交互，外界数据不可靠时，需要使用catch和try <br><br>* 慎重使用process dictory，
当你使用get/1, put/1时，你的应用会具有很大的slide effect。可以通过加入一个新的参数来保存原本需要存储到process
dictory中数据 <br><br>* 如果不想使自己糊涂，请不要使用import <br><br>*
使用export时，将功能类似的接口组合在一起，并添加合理的注视，这样你的接口更清晰，别人使用起来更方便 <br><br>* 不要书写嵌套太深的代码
<br><br>* 不要书写太长的module <br><br>* 不要书写太长的函数 <br><br>* 每行代码不能太长 <br><br>* 避免使用
"_" 匿名变量，请为每个变量选择有意义的名称，如够某个变量暂时不使用，请以下划线 "_" 开始 <br><br>* {error, <span class="hilite2">enfile</span>} <span class="hilite2">enfile</span> error in socket
是以为内linux系统中 ulimit 限制， 在root下修改：ulimit -n 25000 <br><br>* {error, enotconn}
表示socket已经关闭 <br><br>* 在<span class="hilite1">erlang</span>开发时，慎重使用macro，因为<span class="hilite1">erlang</span>的single
assign的缘故，同时调用某个marco，而macro又定义了某个变量，可能导致badmatch错误。 <br>比如：
<br>-define(ADDLINEINFO1(F), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Str1 =
lists:concat(["[Mod:", ?MODULE, " Line:", ?LINE, "]"]), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Str1 ++ F
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )). <br>-define(WARN(Log, F, D), log4erl:warn(Log,
?ADDLINEINFO(F), D)). <br>如果连续使用 WARN, 会出现此错误 <br><br>* <span class="hilite1">erlang</span>中可以定义很多环境变量： <br>ERL_MAX_ETS_TABLES 设置最大的ets数目 默认1400
<br>ERL_MAX_PORTS <span class="hilite1">erlang</span>最大的port数目 默认1024 <br><br>*
.app文件中的start_phases， 选项既可以用来作为include
applications之间的同步启动，也可以用来对单个application进行分布启动。 <br>顺序如下 <br>包含included app:
<br><br>application:start(prim_app) <br>=&gt; prim_app_cb:start(normal, [])
<br>=&gt; prim_app_cb:start_phase(init, normal, []) <br>=&gt;
prim_app_cb:start_phase(go, normal, []) <br>=&gt; incl_app_cb:start_phase(go,
normal, []) <br>ok <br><br>无included app: <br>application:start(prim_app)
<br>=&gt; prim_app_cb:start(normal, []) <br>=&gt; prim_app_cb:start_phase(init,
normal, []) <br>=&gt; prim_app_cb:start_phase(go, normal, []) <br>ok <br><br>*
任何时候，都要重视函数的返回值，通过match确保您的预期，如果发生错误，那么就大胆的表达出来。 <img src ="http://www.cppblog.com/keigoliye/aggbug/97082.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-24 01:00 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/24/97082.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在MacOSX上测试Mochiweb遇到的一些问题</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/24/97081.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Wed, 23 Sep 2009 16:59:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/24/97081.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/97081.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/24/97081.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/97081.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/97081.html</trackback:ping><description><![CDATA[<a  href="http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1/" target="_blank">A Million-user Comet Application with Mochiweb, Part 1</a>
<br>在MacOSX平台上遇到的一些问题： <br><br>一. IPv6导致的问题
<br>在MacOS下测试时报错econnrefused，mochi-urls.txt文件的url不能用localhost，得用127.0.0.1才行
<br><br>在Erlang的邮件列表中找到了解释： <br>We have seen the same issue with CouchDB. What
we found out <br>is that in our case localhost was not only resolving to
127.0.0.1 (IPv4) <br>but also ::1 (IPv6) and that http:request() would try to
connect to <br>::1 where no service was listening.
<br><br>Erlang的http模块缺省是打开IPv6模式的，当测试程序通过http模块连接localhost时，连接的地址是IPv6的::1地址，但是mochi没有在此监听，所以连接出错
{error,econnrefused} <br><br>解决方法两种： <br>1. 将mochi-urls.txt中的地址都改成127.0.0.1
<br>2.
在http:request(&#8230;)运行之前调用http:set_options([{ipv6,disabled}])，关闭测试程序的IPv6模式，使用IPv4模式
<br><br>理论上还有一种方法：让mochi服务器开启IPv6模式监听，这个我不知道这么开， <br>参考 <br>You should teach
Yaws to listen also on IPv6 - &#8220;localhost&#8221; resolves not <br>only to IPv4
127.0.0.1, but also to IPv6 ::1. <br><br><br>二. 进程能打开的文件描述符数量的限制
<br>MacOSX下缺省能同时打开的文件描述符最大数是256个，使用 ulimit -a命令查看 <br>$ ulimit -a <br>core file
size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (blocks, -c) 0 <br>data seg size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (kbytes, -d) 6144
<br>file size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (blocks, -f) unlimited <br>max locked memory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(kbytes, -l) unlimited <br>max memory size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (kbytes, -m) unlimited
<br><strong>open files&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (-n) 256 <br></strong>pipe
size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (512 bytes, -p) 1 <br>stack size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (kbytes, -s) 8192
<br>cpu time&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (seconds, -t) unlimited <br>max user
processes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (-u) 266 <br>virtual memory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (kbytes, -v)
unlimited <br>使用ulimit -n XXXX设置，但最大数量还是不能超过10240 <br><br>查看内核每进程最大文件数： <br>$
sysctl kern.maxfiles kern.maxfilesperproc <br>kern.maxfiles: 12288
<br>kern.maxfilesperproc: 10240 <br><br>增大每进程最大文件数： <br>$ sudo sysctl -w
kern.maxfilesperproc=20480 kern.maxfiles=22528 <br><br>然后设置 <br>$ ulimit -n
20480 <br>注意ulimit只在每个shell窗口生命周期内有效，当新开一个shell后，得再次设置 <br>sysctl做的修改没有这个问题
<br><br>三、调节IP端口号范围，不然最多只能有15K个连接 <br>缺省动态端口号从49152开始，改成2000后最多可以有63K个连接
<br>sysctl -w net.inet.ip.portrange.hifirst=2000
net.inet.ip.portrange.first=2000 <br><img src ="http://www.cppblog.com/keigoliye/aggbug/97081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-24 00:59 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/24/97081.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ubuntu下编译安装Erlang</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/18/96660.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 18 Sep 2009 11:12:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/18/96660.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96660.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/18/96660.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96660.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96660.html</trackback:ping><description><![CDATA[<p>先要这样 <br>apt-get install build-essential&nbsp;&nbsp; <br>apt-get install libncurses5-dev&nbsp;&nbsp; <br>apt-get install m4&nbsp;&nbsp; <br>apt-get install libssl-dev&nbsp; </p>
<p><br>然后要用新立得装如下库： <br>libc6 <br>unixodbc<br>unixodbc-dev<br>gcj <br></p>
<pre>freeglut3-dev<br>libwxgtk2.8-dev<br>g++</pre>
<p><br></p>
<p>然后下载源代码 <br>tar -xvf otp-src-R12B-0.tar.gz&nbsp;&nbsp; <br>cd otp-src-R12B-0&nbsp; <br>sudo ./configure --prefix=/otp/erlang&nbsp;&nbsp; <br>sudo make&nbsp;&nbsp; <br>sudo make install&nbsp; </p>
<p><br>安装完毕，可以rm -fr opt-src-R12B-0删除源代码 </p>
<p>然后改改/etc/profile <br>export PATH=/opt/erlang/bin:$PATH<br>alias ls='ls -color=auto'<br>alias ll='ll -lht'</p>
<p>可以source /etc/profile一下，及时修改PATH <br></p><img src ="http://www.cppblog.com/keigoliye/aggbug/96660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-18 19:12 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/18/96660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang与ActionScript3采用JSON格式进行Socket通讯</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/18/96649.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 18 Sep 2009 08:07:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/18/96649.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96649.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/18/96649.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96649.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96649.html</trackback:ping><description><![CDATA[前提： <br>需要下载<a href="http://code.google.com/p/as3corelib/" target=_blank><u><font color=#006699>as3corelib</font></u></a>来为ActionScript3处理JSON codec <br><br>server.erl <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">-</span><span style="COLOR: #000000">module(server).&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">export([start</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,start</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,process</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]).&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">define(defPort,&nbsp;</span><span style="COLOR: #000000">8888</span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;<br>start()&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;start(</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">defPort).&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;<br>start(Port)&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;gen_tcp:listen(Port,&nbsp;[binary,&nbsp;{packet,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">},&nbsp;{active,&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">}])&nbsp;of&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{ok,&nbsp;LSock}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;server_loop(LSock);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{error,&nbsp;Reason}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;exit({Port,Reason})&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;end.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;<br></span><span style="COLOR: #000000">%%</span><span style="COLOR: #000000">&nbsp;main&nbsp;server&nbsp;loop&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;wait&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;next&nbsp;connection,&nbsp;spawn&nbsp;child&nbsp;to&nbsp;process&nbsp;it&nbsp;&nbsp;&nbsp;<br>server_loop(LSock)&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;gen_tcp:accept(LSock)&nbsp;of&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{ok,&nbsp;Sock}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spawn(</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">MODULE,process,[Sock]),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server_loop(LSock);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{error,&nbsp;Reason}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit({accept,Reason})&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;end.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;<br></span><span style="COLOR: #000000">%%</span><span style="COLOR: #000000">&nbsp;process&nbsp;current&nbsp;connection&nbsp;&nbsp;&nbsp;<br>process(Sock)&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;Req&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;do_recv(Sock),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;io:format(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">~p~n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;[Req]),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;{ok,&nbsp;D,&nbsp;[]}&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(Req),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;{obj,&nbsp;[{</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;_Name},&nbsp;{</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">age</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;Age}]}&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;D,&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;Name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;binary_to_list(_Name),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;io:format(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Name:&nbsp;~p,&nbsp;Age:&nbsp;~p~n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;[Name,&nbsp;Age]),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;Resp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode({obj,&nbsp;[{</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">Hideto2</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">},&nbsp;{</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">age</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">24</span><span style="COLOR: #000000">}]}),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;do_send(Sock,Resp),&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;gen_tcp:close(Sock).&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;<br></span><span style="COLOR: #000000">%%</span><span style="COLOR: #000000">&nbsp;send&nbsp;a&nbsp;line&nbsp;of&nbsp;text&nbsp;to&nbsp;the&nbsp;socket&nbsp;&nbsp;&nbsp;<br>do_send(Sock,Msg)&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;gen_tcp:send(Sock,&nbsp;Msg)&nbsp;of&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ok&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;ok;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{error,&nbsp;Reason}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;exit(Reason)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;end.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;<br></span><span style="COLOR: #000000">%%</span><span style="COLOR: #000000">&nbsp;receive&nbsp;data&nbsp;from&nbsp;the&nbsp;socket&nbsp;&nbsp;&nbsp;<br>do_recv(Sock)&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;gen_tcp:recv(Sock,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;of&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{ok,&nbsp;Bin}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;binary_to_list(Bin);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{error,&nbsp;closed}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;exit(closed);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{error,&nbsp;Reason}&nbsp;</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;exit(Reason)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;end.&nbsp;&nbsp;<br></span></div>
<br>Person.as <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;&nbsp;<br>{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Person&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;var&nbsp;name:String;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;var&nbsp;age:</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;Person()&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>}&nbsp;&nbsp;</span></div>
<br>Client.as <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.adobe.serialization.json.JSON;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.display.Sprite;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.events.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.net.Socket;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.text.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Client&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;Sprite&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;var&nbsp;socket:Socket;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;var&nbsp;myField:TextField;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;var&nbsp;send_data:Person;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;Client()&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Socket();&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myField&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;TextField();&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send_data&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Person();&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send_data.name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hideto</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send_data.age&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">23</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.addEventListener(ProgressEvent.SOCKET_DATA,&nbsp;onSocketData);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.connect(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">localhost</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">8888</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.writeUTFBytes(JSON.encode(send_data));&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.flush();&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myField.x&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myField.y&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">30</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myField.text&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myField.autoSize&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TextFieldAutoSize.LEFT;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addChild(myField);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;function&nbsp;onSocketData(event:ProgressEvent):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(socket.bytesAvailable)&nbsp;{&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;recv_data:</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;JSON.decode(socket.readUTFBytes(socket.bytesAvailable));&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myField.text&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Name:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;recv_data.name&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;age:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;recv_data.age.toString();&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>}&nbsp;</span></div>
<br>运行Erlang服务器端：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Eshell</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;c(server).&nbsp;&nbsp;&nbsp;<br>Eshell</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;server:start().&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">{\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">:\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hideto\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">age\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">:23}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br>Name:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hideto</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;Age:&nbsp;</span><span style="COLOR: #000000">23</span><span style="COLOR: #000000">&nbsp;</span></div>
<br>这里打印出了Erlang Socket Server接收到的AS3 Client发过来的JSON decode过的一个person对象 <br><br>运行AS3客户端： <br>client.html上首先显示&#8220;test&#8221;，然后异步处理完Socket消息发送和接受后，decode Erlang Server端发过来的person对象，将页面上的TextField替换为&#8220;Name: Hideto2, age: 24&#8221; 
<img src ="http://www.cppblog.com/keigoliye/aggbug/96649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-18 16:07 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/18/96649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang的JSON库</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/18/96647.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 18 Sep 2009 07:38:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/18/96647.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96647.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/18/96647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96647.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96647.html</trackback:ping><description><![CDATA[使用下列JSON库： <br><a href="http://www.lshift.net/blog/2007/02/17/json-and-json-rpc-for-erlang" target=_blank><u><font color=#810081>http://www.lshift.net/blog/2007/02/17/json-and-json-rpc-for-erlang</font></u></a> <br><br>该JSON库采用<a href="http://www.erlang.org/ml-archive/erlang-questions/200511/msg00193.html" target=_blank><u><font color=#0000ff>Joe Armstrong prefered Data type mapping</font></u></a> <br>即： <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_29_51_Open_Image onclick="this.style.display='none'; Codehighlighter1_29_51_Open_Text.style.display='none'; Codehighlighter1_29_51_Closed_Image.style.display='inline'; Codehighlighter1_29_51_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_29_51_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_29_51_Closed_Text.style.display='none'; Codehighlighter1_29_51_Open_Image.style.display='inline'; Codehighlighter1_29_51_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">JSON&nbsp;Obj&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;type&nbsp;obj()&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_29_51_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_29_51_Open_Text><span style="COLOR: #000000">{obj,&nbsp;[</span><span id=Codehighlighter1_36_49_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_36_49_Open_Text><span style="COLOR: #000000">{key(),&nbsp;val()}</span></span><span style="COLOR: #000000">]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>JSON&nbsp;Array&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;type&nbsp;array()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;[val()]&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>JSON&nbsp;Number&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;type&nbsp;num()&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">()&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">()&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>JSON&nbsp;String&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;type&nbsp;str()&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;bin()&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>JSON&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;(atoms)&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>With&nbsp;Type&nbsp;val()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;obj()&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;array()&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;num()&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;str()&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>and&nbsp;key()&nbsp;being&nbsp;a&nbsp;str().&nbsp;(Or&nbsp;a&nbsp;binary&nbsp;or&nbsp;atom,&nbsp;during&nbsp;JSON&nbsp;encoding.)&nbsp;&nbsp;</span></div>
<br>测试如下： <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">Eshell&nbsp;V5.</span><span style="COLOR: #000000">6.3</span><span style="COLOR: #000000">&nbsp;&nbsp;(abort&nbsp;with&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">G)&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_56_89_Open_Image onclick="this.style.display='none'; Codehighlighter1_56_89_Open_Text.style.display='none'; Codehighlighter1_56_89_Closed_Image.style.display='inline'; Codehighlighter1_56_89_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_56_89_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_56_89_Closed_Text.style.display='none'; Codehighlighter1_56_89_Open_Image.style.display='inline'; Codehighlighter1_56_89_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;O&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode(</span><span id=Codehighlighter1_56_89_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_56_89_Open_Text><span style="COLOR: #000000">{obj,&nbsp;[</span><span id=Codehighlighter1_63_76_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_63_76_Open_Text><span style="COLOR: #000000">{name,&nbsp;hideto}</span></span><span style="COLOR: #000000">,&nbsp;</span><span id=Codehighlighter1_79_87_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_79_87_Open_Text><span style="COLOR: #000000">{age,&nbsp;</span><span style="COLOR: #000000">23</span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">]}</span></span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">{\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">:\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hideto\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">age\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">:23}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(O).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_164_211_Open_Image onclick="this.style.display='none'; Codehighlighter1_164_211_Open_Text.style.display='none'; Codehighlighter1_164_211_Closed_Image.style.display='inline'; Codehighlighter1_164_211_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_164_211_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_164_211_Closed_Text.style.display='none'; Codehighlighter1_164_211_Open_Image.style.display='inline'; Codehighlighter1_164_211_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_164_211_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_164_211_Open_Text><span style="COLOR: #000000">{ok,</span><span id=Codehighlighter1_168_207_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_168_207_Open_Text><span style="COLOR: #000000">{obj,[</span><span id=Codehighlighter1_174_194_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_174_194_Open_Text><span style="COLOR: #000000">{</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hideto</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">,</span><span id=Codehighlighter1_196_205_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_196_205_Open_Text><span style="COLOR: #000000">{</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">age</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">23</span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">]}</span></span><span style="COLOR: #000000">,[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;A&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode([</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">]).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">[1,2,3,4,5]</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(A).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_296_314_Open_Image onclick="this.style.display='none'; Codehighlighter1_296_314_Open_Text.style.display='none'; Codehighlighter1_296_314_Closed_Image.style.display='inline'; Codehighlighter1_296_314_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_296_314_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_296_314_Closed_Text.style.display='none'; Codehighlighter1_296_314_Open_Image.style.display='inline'; Codehighlighter1_296_314_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_296_314_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_296_314_Open_Text><span style="COLOR: #000000">{ok,[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">],[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;N&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode(</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(N).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_387_399_Open_Image onclick="this.style.display='none'; Codehighlighter1_387_399_Open_Text.style.display='none'; Codehighlighter1_387_399_Closed_Image.style.display='inline'; Codehighlighter1_387_399_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_387_399_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_387_399_Closed_Text.style.display='none'; Codehighlighter1_387_399_Open_Image.style.display='inline'; Codehighlighter1_387_399_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_387_399_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_387_399_Open_Text><span style="COLOR: #000000">{ok,</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">,[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">7</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;S&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">[49,50,51,52,53]</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(S).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_485_499_Open_Image onclick="this.style.display='none'; Codehighlighter1_485_499_Open_Text.style.display='none'; Codehighlighter1_485_499_Closed_Image.style.display='inline'; Codehighlighter1_485_499_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_485_499_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_485_499_Closed_Text.style.display='none'; Codehighlighter1_485_499_Open_Image.style.display='inline'; Codehighlighter1_485_499_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_485_499_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_485_499_Open_Text><span style="COLOR: #000000">{ok,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;T&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">true</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(T).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_571_582_Open_Image onclick="this.style.display='none'; Codehighlighter1_571_582_Open_Text.style.display='none'; Codehighlighter1_571_582_Closed_Image.style.display='inline'; Codehighlighter1_571_582_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_571_582_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_571_582_Closed_Text.style.display='none'; Codehighlighter1_571_582_Open_Image.style.display='inline'; Codehighlighter1_571_582_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_571_582_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_571_582_Open_Text><span style="COLOR: #000000">{ok,</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">,[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">11</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;F&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode(</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">false</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">12</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(F).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_657_669_Open_Image onclick="this.style.display='none'; Codehighlighter1_657_669_Open_Text.style.display='none'; Codehighlighter1_657_669_Closed_Image.style.display='inline'; Codehighlighter1_657_669_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_657_669_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_657_669_Closed_Text.style.display='none'; Codehighlighter1_657_669_Open_Image.style.display='inline'; Codehighlighter1_657_669_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_657_669_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_657_669_Open_Text><span style="COLOR: #000000">{ok,</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">,[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">13</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;Null&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rfc4627:encode(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">).&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">null</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">14</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;rfc4627:decode(Null).&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_748_759_Open_Image onclick="this.style.display='none'; Codehighlighter1_748_759_Open_Text.style.display='none'; Codehighlighter1_748_759_Closed_Image.style.display='inline'; Codehighlighter1_748_759_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_748_759_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_748_759_Closed_Text.style.display='none'; Codehighlighter1_748_759_Open_Image.style.display='inline'; Codehighlighter1_748_759_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_748_759_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_748_759_Open_Text><span style="COLOR: #000000">{ok,</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">,[]}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>
<img src ="http://www.cppblog.com/keigoliye/aggbug/96647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-18 15:38 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/18/96647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Flash Socket 和 Erlang Socket 通信的注意事项</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/18/96634.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 18 Sep 2009 04:40:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/18/96634.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96634.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/18/96634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96634.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96634.html</trackback:ping><description><![CDATA[<p>转自<a href="http://www.javaeye.com/topic/401041">http://www.javaeye.com/topic/401041</a><br><br><br>学erlang有一段时间了，现在在维护一套webim系统 <br>并打算扩展成 webgame 的服务程序</p>
<p>在没有使用包协议的时候，遇到好多粘包问题，实在恼火</p>
<p>查阅了相关资料：</p>
<p>Flash Socket 的 writeUTF() 会自动增加包头长度的协议，刚好对应了 <br>Erlang的Socket选项 {packet,2} <br><br>这使得两者的通信非常完美，再也不用担心粘包什么的问题了</p>
<p>&nbsp;</p>
<p>下面是我写的一个Flash Socket 接口：SocketBridge.as</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_8_2502_Open_Image onclick="this.style.display='none'; Codehighlighter1_8_2502_Open_Text.style.display='none'; Codehighlighter1_8_2502_Closed_Image.style.display='inline'; Codehighlighter1_8_2502_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_8_2502_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_8_2502_Closed_Text.style.display='none'; Codehighlighter1_8_2502_Open_Image.style.display='inline'; Codehighlighter1_8_2502_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_8_2502_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_8_2502_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.display.Sprite;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.events.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.net.Socket;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.utils.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.external.ExternalInterface;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;flash.system.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_263_2497_Open_Image onclick="this.style.display='none'; Codehighlighter1_263_2497_Open_Text.style.display='none'; Codehighlighter1_263_2497_Closed_Image.style.display='inline'; Codehighlighter1_263_2497_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_263_2497_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_263_2497_Closed_Text.style.display='none'; Codehighlighter1_263_2497_Open_Image.style.display='inline'; Codehighlighter1_263_2497_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;SocketBridge&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;Sprite&nbsp;</span><span id=Codehighlighter1_263_2497_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_263_2497_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket.prototype.timeout&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">3000</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;var&nbsp;socket:Socket;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;SocketBridge()&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_402_1096_Open_Image onclick="this.style.display='none'; Codehighlighter1_402_1096_Open_Text.style.display='none'; Codehighlighter1_402_1096_Closed_Image.style.display='inline'; Codehighlighter1_402_1096_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_402_1096_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_402_1096_Closed_Text.style.display='none'; Codehighlighter1_402_1096_Open_Image.style.display='inline'; Codehighlighter1_402_1096_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_402_1096_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_402_1096_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Socket();&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.addEventListener(&nbsp;Event.CONNECT,&nbsp;onConnect&nbsp;);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.addEventListener(&nbsp;ProgressEvent.SOCKET_DATA,&nbsp;onDataRecevice);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.addEventListener(&nbsp;Event.CLOSE,&nbsp;onClose);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.addEventListener(&nbsp;IOErrorEvent.IO_ERROR,&nbsp;onError);&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(ExternalInterface.available)&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_809_1083_Open_Image onclick="this.style.display='none'; Codehighlighter1_809_1083_Open_Text.style.display='none'; Codehighlighter1_809_1083_Closed_Image.style.display='inline'; Codehighlighter1_809_1083_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_809_1083_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_809_1083_Closed_Text.style.display='none'; Codehighlighter1_809_1083_Open_Image.style.display='inline'; Codehighlighter1_809_1083_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_809_1083_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_809_1083_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.addCallback(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">socket_connect</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,socket_connect);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.addCallback(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">socket_send</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,socket_send);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.addCallback(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">load_policy</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,load_policy);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;onError(e):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img id=Codehighlighter1_1151_1255_Open_Image onclick="this.style.display='none'; Codehighlighter1_1151_1255_Open_Text.style.display='none'; Codehighlighter1_1151_1255_Closed_Image.style.display='inline'; Codehighlighter1_1151_1255_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1151_1255_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1151_1255_Closed_Text.style.display='none'; Codehighlighter1_1151_1255_Open_Image.style.display='inline'; Codehighlighter1_1151_1255_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1151_1255_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1151_1255_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.call(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sb_onerror</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,e.text);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;load_policy(host:String,port):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img id=Codehighlighter1_1329_1414_Open_Image onclick="this.style.display='none'; Codehighlighter1_1329_1414_Open_Text.style.display='none'; Codehighlighter1_1329_1414_Closed_Image.style.display='inline'; Codehighlighter1_1329_1414_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1329_1414_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1329_1414_Closed_Text.style.display='none'; Codehighlighter1_1329_1414_Open_Image.style.display='inline'; Codehighlighter1_1329_1414_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1329_1414_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1329_1414_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Security.loadPolicyFile(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">xmlsocket://</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">host</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">port);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;socket_connect(host:String,port):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img id=Codehighlighter1_1503_1689_Open_Image onclick="this.style.display='none'; Codehighlighter1_1503_1689_Open_Text.style.display='none'; Codehighlighter1_1503_1689_Closed_Image.style.display='inline'; Codehighlighter1_1503_1689_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1503_1689_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1503_1689_Closed_Text.style.display='none'; Codehighlighter1_1503_1689_Open_Image.style.display='inline'; Codehighlighter1_1503_1689_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1503_1689_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1503_1689_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_1523_1586_Open_Image onclick="this.style.display='none'; Codehighlighter1_1523_1586_Open_Text.style.display='none'; Codehighlighter1_1523_1586_Closed_Image.style.display='inline'; Codehighlighter1_1523_1586_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1523_1586_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1523_1586_Closed_Text.style.display='none'; Codehighlighter1_1523_1586_Open_Image.style.display='inline'; Codehighlighter1_1523_1586_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span id=Codehighlighter1_1523_1586_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1523_1586_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.connect(host,port);&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_1595_1676_Open_Image onclick="this.style.display='none'; Codehighlighter1_1595_1676_Open_Text.style.display='none'; Codehighlighter1_1595_1676_Closed_Image.style.display='inline'; Codehighlighter1_1595_1676_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1595_1676_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1595_1676_Closed_Text.style.display='none'; Codehighlighter1_1595_1676_Open_Image.style.display='inline'; Codehighlighter1_1595_1676_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(e)</span><span id=Codehighlighter1_1595_1676_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1595_1676_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.call(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sb_onerror</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,e.text);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;function&nbsp;socket_send(msg:String)&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_1765_1849_Open_Image onclick="this.style.display='none'; Codehighlighter1_1765_1849_Open_Text.style.display='none'; Codehighlighter1_1765_1849_Closed_Image.style.display='inline'; Codehighlighter1_1765_1849_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1765_1849_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1765_1849_Closed_Text.style.display='none'; Codehighlighter1_1765_1849_Open_Image.style.display='inline'; Codehighlighter1_1765_1849_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1765_1849_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1765_1849_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.writeUTF(msg);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.flush();&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;function&nbsp;onConnect(event:Event):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_1931_2004_Open_Image onclick="this.style.display='none'; Codehighlighter1_1931_2004_Open_Text.style.display='none'; Codehighlighter1_1931_2004_Closed_Image.style.display='inline'; Codehighlighter1_1931_2004_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1931_2004_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1931_2004_Closed_Text.style.display='none'; Codehighlighter1_1931_2004_Open_Image.style.display='inline'; Codehighlighter1_1931_2004_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1931_2004_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1931_2004_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.call(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sb_onconnect</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;function&nbsp;onClose(event:Event):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_2084_2186_Open_Image onclick="this.style.display='none'; Codehighlighter1_2084_2186_Open_Text.style.display='none'; Codehighlighter1_2084_2186_Closed_Image.style.display='inline'; Codehighlighter1_2084_2186_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2084_2186_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2084_2186_Closed_Text.style.display='none'; Codehighlighter1_2084_2186_Open_Image.style.display='inline'; Codehighlighter1_2084_2186_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_2084_2186_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_2084_2186_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.call(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sb_onclose</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;function&nbsp;onDataRecevice(&nbsp;eventrogressEvent&nbsp;):</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img id=Codehighlighter1_2270_2485_Open_Image onclick="this.style.display='none'; Codehighlighter1_2270_2485_Open_Text.style.display='none'; Codehighlighter1_2270_2485_Closed_Image.style.display='inline'; Codehighlighter1_2270_2485_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2270_2485_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2270_2485_Closed_Text.style.display='none'; Codehighlighter1_2270_2485_Open_Image.style.display='inline'; Codehighlighter1_2270_2485_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_2270_2485_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_2270_2485_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;sdata:String;&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_2348_2472_Open_Image onclick="this.style.display='none'; Codehighlighter1_2348_2472_Open_Text.style.display='none'; Codehighlighter1_2348_2472_Closed_Image.style.display='inline'; Codehighlighter1_2348_2472_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2348_2472_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2348_2472_Closed_Text.style.display='none'; Codehighlighter1_2348_2472_Open_Image.style.display='inline'; Codehighlighter1_2348_2472_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(socket.bytesAvailable)</span><span id=Codehighlighter1_2348_2472_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_2348_2472_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sdata&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;socket.readUTF();&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExternalInterface.call(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sb_ondata</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,sdata);&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cppblog.com/keigoliye/aggbug/96634.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-18 12:40 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/18/96634.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>erlang网络编程的几个性能调优和注意点</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/14/96106.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Mon, 14 Sep 2009 04:25:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/14/96106.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96106.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/14/96106.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96106.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96106.html</trackback:ping><description><![CDATA[转自http://coderplay.javaeye.com/blog/94209<br><br>前些天给echo_server写了个非常简单的连接压力测试程序,
<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">.&nbsp;&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">module(stress_test).&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">.&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">export([start</span><span style="color: #000000;">/</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;tests</span><span style="color: #000000;">/</span><span style="color: #000000;">1</span><span style="color: #000000;">]).&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">.&nbsp;start()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">6</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tests(</span><span style="color: #000000;">12345</span><span style="color: #000000;">).&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">7</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">.&nbsp;tests(Port)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">9</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(</span><span style="color: #000000;">"</span><span style="color: #000000;">starting~n</span><span style="color: #000000;">"</span><span style="color: #000000;">),&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spawn(fun()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;test(Port)&nbsp;end),&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">11</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spawn(fun()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;test(Port)&nbsp;end),&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">12</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spawn(fun()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;test(Port)&nbsp;end),&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">13</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spawn(fun()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;test(Port)&nbsp;end).&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">14</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">15</span><span style="color: #000000;">.&nbsp;test(Port)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">16</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;gen_tcp:connect(</span><span style="color: #000000;">"</span><span style="color: #000000;">192.168.0.217</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;Port,&nbsp;[binary,{packet,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">}])&nbsp;of&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">17</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ok,&nbsp;_}&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">18</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test(Port);&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">19</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">20</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test(Port)&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">21</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;<br></span></div>
一开始我的这个stress_test客户端运行在windows上面, echo_server服务器端运行在linux上面。
结果接受了1016个连接就停止了. 于是我用ulimit -n 改了服务器端的文件描述符数量为10240.
接着还是如此,折腾了几天,最终还是没有搞明白。 <br>
<br>
于是就求助于公司的linux编程牛人,结果让我一倒...&nbsp; 客户端没有修改文件描述符个数. windows上得在注册表里面改. <br>
牛人开始对这东西的性能感兴趣了,刚好我摸了一阵子erlang的文档,于是我俩就走向了erlang网络连接的性能调优之旅啦~~过程真是让人兴奋。 我们很快通过了1024这一关~~到了4999个连接,很兴奋. <br>
<br>
但为什么4999个连接呢, 检查一下代码终于发现echo_server.erl定义了一个宏, 最大连接数为5000. 我又倒~~<br>
修改编译之后, 连接数跑到101xx多了, 太哈皮了!<br>
再测102400个连接时,到32767个连接数erl挂了~说是进程开得太多了. 好在记得这个erl的参数+P,可以定义erlang能生成的进程数. 默认是32768. 改了!<br>
<br>
后面不知怎么着,在81231个连接停止了. 新的性能瓶颈又卡了我们.&nbsp; 好在牛人对linux熟, 用strace(这东西会莫名地退出),
stap查出一些苗头.&nbsp;&nbsp;
我也想到在otp文档好像提过另一个limit,那就是端口数...在此同时我们发现erlang在linux上是用的传统poll模型.
但查erlang的源代码发现是支持epoll的. 在网上搜了半天,终于搜到了个maillist的帖子. <br>
<br>
<div class="code_title">代码</div>
<div class="dp-highlighter">
<ol class="dp-j" start="1">
    <li class="alt"><span><span>$./configure&nbsp;--enable-kernel-poll&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br>
由于我们的测试服务器是双核的,我们在配置的时候也打开了smp支持.&nbsp; 欢快的make&nbsp; &amp; make install之后....<br>
把 /proc/sys/net/ipv4/ip_local_port_range 的内容改成了1024到65535.&nbsp; 最多也也能改成65535 :)<br>
<br>
<div class="code_title">代码</div>
<div class="dp-highlighter">
<ol class="dp-j" start="1">
    <li class="alt"><span><span>$echo&nbsp;</span><span class="number">1024</span><span>&nbsp;</span><span class="number">65535</span><span>&nbsp;&gt;&nbsp;ip_local_port_range&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br>
另外再添加一个erl的环境变量<br>
<div class="code_title">代码</div>
<div class="dp-highlighter">
<ol class="dp-j" start="1">
    <li class="alt"><span><span>$export&nbsp;ERL_MAX_PORTS=</span><span class="number">102400</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br>
于是开始跑了,不过这次跑不一样了<br>
<div class="code_title">echo_server</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span>$erl&nbsp;-noshell&nbsp;&nbsp;+P&nbsp;</span><span class="number">102400</span><span>&nbsp;+K&nbsp;</span><span class="keyword">true</span><span> </span></span><code>+S 2 -smp </code><span><span>-s echo_server&nbsp;start&nbsp;&nbsp;</span></span></li>
</ol>
</div>
&nbsp;&nbsp;&nbsp;
<div class="code_title">stress_test</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span>$erl&nbsp;-noshell&nbsp;&nbsp;+P&nbsp;</span><span class="number">102400</span><span>&nbsp;+K&nbsp;</span><span class="keyword">true</span><span> </span></span><code>+S 2 -smp </code><span><span>-s stress_test&nbsp;start&nbsp;&nbsp;</span></span></li>
</ol>
</div>
这里的+K true,<code>表示使用内核poll,<code>+S 2 表示两个核. </code>这样可欢快啦~~~ 10w大关过咯! 而且比刚才没用epoll的速度快暴多~~<br>
于是我们又开始了204800个连接发测试了~~~<br>
<br>
用top一看cpu占用率极低,服务器只在5%左右。 内存也不是很大~~
</code><br><img src ="http://www.cppblog.com/keigoliye/aggbug/96106.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-14 12:25 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/14/96106.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>echo_server </title><link>http://www.cppblog.com/keigoliye/archive/2009/09/14/96105.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Mon, 14 Sep 2009 04:24:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/14/96105.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96105.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/14/96105.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96105.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96105.html</trackback:ping><description><![CDATA[转自http://coderplay.javaeye.com/blog/93403<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">.&nbsp;&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">module(echo_server).&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">.&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">export([start</span><span style="color: #000000;">/</span><span style="color: #000000;">0</span><span style="color: #000000;">,stop</span><span style="color: #000000;">/</span><span style="color: #000000;">0</span><span style="color: #000000;">]).&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">.&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">define(LISTEN_PORT,</span><span style="color: #000000;">12345</span><span style="color: #000000;">).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;开放端口&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">.&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">define(MAX_CONN,&nbsp;</span><span style="color: #000000;">5000</span><span style="color: #000000;">).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;最大连接数&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">6</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">7</span><span style="color: #000000;">.&nbsp;start()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process_flag(trap_exit,&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">),&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;设置退出陷阱&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">9</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tcp_server:start_raw_server(</span><span style="color: #000000;">?</span><span style="color: #000000;">LISTEN_PORT,&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fun(Socket)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;socket_handler(Socket,self())&nbsp;end,&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">11</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">MAX_CONN,&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">12</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">).&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">13</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">14</span><span style="color: #000000;">.&nbsp;</span><span style="color: #000000;">%%</span><span style="color: #000000;">&nbsp;处理数据&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">15</span><span style="color: #000000;">.&nbsp;socket_handler(Socket,Controller)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">16</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">17</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{tcp,&nbsp;Socket,&nbsp;Bin}&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">18</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gen_tcp:send(Socket,&nbsp;Bin);&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;echo&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">19</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{tcp_closed,&nbsp;Socket}&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">20</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ok;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">21</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">22</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket_handler(Socket,Controller)&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">23</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">24</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">25</span><span style="color: #000000;">.&nbsp;stop()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="color: #000000;">26</span><span style="color: #000000;">.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tcp_server:stop(</span><span style="color: #000000;">?</span><span style="color: #000000;">LISTEN_PORT).&nbsp;&nbsp;<br></span></div>
<br>基于Joe Armstrong 的tcp_server模块来做的, 试试先 :)<br>
<br>
编译 <br>
&nbsp;&nbsp;&nbsp; erl -noshell -s make all -s init stop<br>
运行<br>
&nbsp;&nbsp;&nbsp; erl -noshell -sname coderplay -s echo_server start
<br><img src ="http://www.cppblog.com/keigoliye/aggbug/96105.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-14 12:24 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/14/96105.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>erlang 网络调优实战</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/14/96096.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Mon, 14 Sep 2009 03:20:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/14/96096.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/96096.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/14/96096.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/96096.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/96096.html</trackback:ping><description><![CDATA[原文网址：<a  href="http://coderplay.javaeye.com/blog/94209" target="_blank"><span href="http://bbs.erlangchina.net/tag.php?name=erlang" onclick="tagshow(event)" class="t_tag">erlang</span><span href="http://bbs.erlangchina.net/tag.php?name=%E7%BD%91%E7%BB%9C" onclick="tagshow(event)" class="t_tag">网络</span><span href="http://bbs.erlangchina.net/tag.php?name=%E7%BC%96%E7%A8%8B" onclick="tagshow(event)" class="t_tag">编程</span>的几个性能<span href="http://bbs.erlangchina.net/tag.php?name=%E8%B0%83%E4%BC%98" onclick="tagshow(event)" class="t_tag">调优</span>和注意点</a><br>
原文作者：<a  href="http://coderplay.javaeye.com/" target="_blank">coderplay</a><br>
前些天给echo_server写了个非常简单的连接压力测试程序,<br>
<span href="http://bbs.erlangchina.net/tag.php?name=%E4%B8%8B%E8%BD%BD" onclick="tagshow(event)" class="t_tag">下载</span>: <a  href="http://erlang-china.org/wordpress/wp-content/plugins/coolcode/coolcode.php?p=71&amp;download=stress_test.erl" target="_blank">stress_test.erl</a><br>
<ul class="litype_1" type="1">
    <li><font color="Gray">-</font><font color="Blue">module</font><font color="Olive">(</font><font color="Blue">stress_test</font><font color="Olive">)</font><font color="Gray">.&nbsp;&nbsp;</font></li>
    <li><br>
    </li>
    <li><font color="Gray">-</font><font color="Blue">export</font><font color="Olive">([</font><font color="Blue">start</font><font color="Gray">/</font><font color="Maroon">0</font><font color="Gray">, </font><font color="Blue">tests</font><font color="Gray">/</font><font color="Maroon">1</font><font color="Olive">])</font><font color="Gray">.&nbsp;&nbsp;</font></li>
    <li><br>
    </li>
    <li><font color="Blue">start</font><font color="Olive">()</font><font color="Gray"> -&gt;&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">tests</font><font color="Olive">(</font><font color="Maroon">12345</font><font color="Olive">)</font><font color="Gray">.&nbsp;&nbsp;</font></li>
    <li><br>
    </li>
    <li><font color="Blue">tests</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><font color="Gray"> -&gt;&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">io</font><font color="Gray">:</font><font color="Blue">format</font><font color="Olive">(</font><font color="#8b0000">"</font><font color="Red">starting~n</font><font color="#8b0000">"</font><font color="Olive">)</font><font color="Gray">,&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">spawn</font><font color="Olive">(</font><font color="Green">fun</font><font color="Olive">()</font><font color="Gray"> -&gt; </font><font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><br>
    <font color="Green">end</font><font color="Olive">)</font><font color="Gray">,&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">spawn</font><font color="Olive">(</font><font color="Green">fun</font><font color="Olive">()</font><font color="Gray"> -&gt; </font><font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><br>
    <font color="Green">end</font><font color="Olive">)</font><font color="Gray">,&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">spawn</font><font color="Olive">(</font><font color="Green">fun</font><font color="Olive">()</font><font color="Gray"> -&gt; </font><font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><br>
    <font color="Green">end</font><font color="Olive">)</font><font color="Gray">,&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">spawn</font><font color="Olive">(</font><font color="Green">fun</font><font color="Olive">()</font><font color="Gray"> -&gt; </font><font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><br>
    <font color="Green">end</font><font color="Olive">)</font><font color="Gray">.&nbsp;&nbsp;</font></li>
    <li><br>
    </li>
    <li><font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><font color="Gray"> -&gt;&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Green">case</font><br>
    <font color="Blue">gen_tcp</font><font color="Gray">:</font><font color="Blue">connect</font><font color="Olive">(</font><font color="#8b0000">"</font><font color="Red">192.168.0.217</font><font color="#8b0000">"</font><font color="Gray">, </font><font color="Blue">Port</font><font color="Gray">, </font><font color="Olive">[</font><font color="Blue">binary</font><font color="Gray">,{</font><font color="Blue">packet</font><font color="Gray">, </font><font color="Maroon">0</font><font color="Gray">}</font><font color="Olive">])</font><br>
    <font color="Green">of</font><br>
    </li>
    <li><font color="Gray">&nbsp; &nbsp; {</font><font color="Blue">ok</font><font color="Gray">, </font><font color="Blue">_</font><font color="Gray">} -&gt;&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><font color="Gray">;&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">_</font><font color="Gray"> -&gt;&nbsp;&nbsp;</font></li>
    <li><br>
    <font color="Blue">test</font><font color="Olive">(</font><font color="Blue">Port</font><font color="Olive">)</font><br>
    </li>
    <li><br>
    <font color="Green">end</font><font color="Gray">.</font></li>
</ul>
<br>
一开始我的这个stress_test客户端运行在<span href="http://bbs.erlangchina.net/tag.php?name=windows" onclick="tagshow(event)" class="t_tag">windows</span>上面,echo_server服务器端运行在linux上面。结果接受了1016个连接就停止了. 于是我用ulimit -n改了服务器端的<span href="http://bbs.erlangchina.net/tag.php?name=%E6%96%87%E4%BB%B6" onclick="tagshow(event)" class="t_tag">文件</span>描述符数量为10240. 接着还是如此,折腾了几天,最终还是没有搞明白。<br>
于是就求助于公司的linux编程牛人,结果让我一倒&#8230;&nbsp;&nbsp;客户端没有修改文件描述符个数. windows上得在注册表里面改.<br>
<br>
牛人开始对这东西的性能感兴趣了,刚好我摸了一阵子erlang的<span href="http://bbs.erlangchina.net/tag.php?name=%E6%96%87%E6%A1%A3" onclick="tagshow(event)" class="t_tag">文档</span>,于是我俩就走向了erlang网络连接的性能调优之旅啦~~过程真是让人兴奋。 我们很快通过了1024这一关~~到了4999个连接,很兴奋.<br>
但为什么4999个连接呢, 检查一下代码终于发现echo_server.erl定义了一个宏, 最大连接数为5000. 我又倒~~<br>
修改<span href="http://bbs.erlangchina.net/tag.php?name=%E7%BC%96%E8%AF%91" onclick="tagshow(event)" class="t_tag">编译</span>之后, 连接数跑到101xx多了, 太哈皮了!<br>
再测102400个连接时,到32767个连接数erl挂了~说是<span href="http://bbs.erlangchina.net/tag.php?name=%E8%BF%9B%E7%A8%8B" onclick="tagshow(event)" class="t_tag">进程</span>开得太多了. 好在记得这个erl的参数+P,可以定义erlang能生成的进程数. 默认是32768. 改了!<br>
后面不知怎么着,在81231个连接停止了. 新的性能瓶颈又卡了我们. 好在牛人对linux熟,
用strace(这东西会莫名地退出),stap查出一些苗头.我也想到在otp文档好像提过另一个limit,那就是端口数&#8230;在此同时我们发现
erlang在linux上是用的传统poll模型.但查erlang的源代码发现是支持epoll的.
在网上搜了半天,终于搜到了个maillist的帖子.<br>
<ul class="litype_1" type="1">
    <li>$./configure --enable-kernel-poll</li>
</ul>
<br>
由于我们的测试服务器是双核的,我们在配置的时候也打开了smp支持. 欢快的make&nbsp;&nbsp;&amp; make install之后&#8230;.<br>
把 /proc/sys/net/ipv4/ip_local_port_range 的内容改成了1024到65535. 最多也也能改成65535 <img  src="http://erlang-china.org/wordpress/wp-includes/images/smilies/icon_smile.gif" onload="thumbImg(this)" alt="" height="15" width="15"> <br>
<ul class="litype_1" type="1">
    <li>$echo 1024 65535 &gt; ip_local_port_range</li>
</ul>
<br>
另外再添加一个erl的环境<span href="http://bbs.erlangchina.net/tag.php?name=%E5%8F%98%E9%87%8F" onclick="tagshow(event)" class="t_tag">变量</span><br>
<ul class="litype_1" type="1">
    <li>$export ERL_MAX_PORTS=102400</li>
</ul>
<br>
于是开始跑了,不过这次跑不一样了<br>
echo_server<br>
<ul class="litype_1" type="1">
    <li>$erl -noshell&nbsp;&nbsp;+P 102400 +K true +S 2 -smp -s echo_server start</li>
</ul>
<br>
stress_test<br>
<ul class="litype_1" type="1">
    <li>$erl -noshell&nbsp;&nbsp;+P 102400 +K true +S 2 -smp -s stress_test start</li>
</ul>
<br>
这里的+K true,表示<span href="http://bbs.erlangchina.net/tag.php?name=%E4%BD%BF%E7%94%A8" onclick="tagshow(event)" class="t_tag">使用</span>内核poll,+S 2 表示两个核. 这样可欢快啦~~~ 10w大关过咯! 而且比刚才没用epoll的速度快暴多~~<br>
于是我们又开始了204800个连接发测试了~~~<br>
用top一看cpu占用率极低,服务器只在5%左右。内存也不是很大~~<img src ="http://www.cppblog.com/keigoliye/aggbug/96096.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-14 11:20 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/14/96096.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ErLang语法提要</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/11/95894.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 11 Sep 2009 03:04:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/11/95894.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/95894.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/11/95894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/95894.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/95894.html</trackback:ping><description><![CDATA[ErLang语法中充满了一些约定。大写字母开头的名字（比如Address），表示一个变量，包括参数、局部变量等；小写字母开头的单词（比如ok），表示一个常量，叫做atom（原子的意思），包括常量名、函数名、模块名等。 <br><br>ErLang的注释用%开头。ErLang用下划线&#8220;_&#8221;表示任意变量，类似于Java的switch语法里面的default选项。 <br><br>ErLang脱胎于Prolog，不过，我觉得，ErLang语法和Haskell语法比较象，都是采用 -&gt; 定义函数。 <br><br>ErLang语句中的标点符号用法很象文章的标点符号。 <br><br>整个函数定义结束用一个句号&#8220;.&#8221;；同一个函数中，并列的逻辑分支之间，用分号&#8220;;&#8221;分界；顺序语句之间，用逗号&#8220;,&#8221;分隔。 <br><br>ErLang中，{ }不是表示程序块的开头和结尾，而是表示一种特殊的数据结构类型——Tuple（元组），比如，{12, 3, ok}。我们可以把Tuple理解为定长数组。 <br><br>[ ] 则表示最基本的函数式编程的数据结构类型——List。List数据结构很基本，写法和用法也有一定的复杂度，不是表面上看起来那么简单，后面讲解Closure的章节会详细介绍List的最基本的构造原理。 <br><br>下面我们来看一个简单的例子。 <br><br>我们首先定义一个最简单的函数，把一个参数乘以10，然后加1。 <br>times10( Number ) &#8211;&gt; <br>Temp = 10 * Number, <br>Temp + 1. <br><br>为了说明问题，上面的代码把乘法操作和加法操作分成两个步骤。Temp = 10 * Number语句后面是逗号，因为这是两条顺序执行的语句。Temp + 1语句后面是句号，表示整个函数定义结束。而且，可以看出，ErLang没有return语句，最后执行的那条语句的执行结果就是返回值。 <br><br>下面，我们把这个函数优化一下。当参数等于0的时候，直接返1；否则，就乘以10，然后加1，然后返回。这时候，我们就要用到case of逻辑分支语句，相当于java的switch语句。 <br><br>times10( Number ) &#8211;&gt; <br>case Number of <br>0 -&gt; 1; <br>_ -&gt; <br>Temp = 10 * Number, <br>Temp + 1 <br>end. <br><br>我们来仔细观察这段ErLang程序。 <br><br>当Number等于0的时候，直接返回1。由于这是一条分支语句，和后面的分支是并列的关系，所以，1的后面的标点符号是分号。后面这个分支，下划线&#8220;_&#8221;表示任何其它值，这里就表示除了1之外的任何其它数值。 <br><br>需要注意的一点是，case of语句需要用end结尾，end之前不需要有标点符号。 <br><br>上述代码中的case of 语句，其实就是Pattern Match的一种。ErLang的Pattern Match很强大，能够大幅度简化程序逻辑，后面进行专门介绍。 <br>Pattern Match <br>Pattern Match主要有两个功能——比较分派和变量赋值。 <br>其中，比较分派是最主要的功能。比较分派的意思是，根据参数值进行条件分支的分派。可以把比较分派功能看作是一种类似于if, else等条件分支语句的简洁强大写法。 <br>上面的例子中，case Number of 就是根据Number的值进行比较分派。更常见的写法是，可以把Pattern Match部分提到函数定义分支的高度。于是，上述代码可以写成下面的形式： <br>times10( 0 ) &#8211;&gt; 1; <br>times10( Number ) &#8211;&gt; <br>Temp = 10 * Number, <br>Temp + 1. <br><br>这段代码由两个函数定义分支构成，由于两个函数分支的函数名相同，而且参数个数相同，而且两个函数定义分支之间采用分号&#8220;;&#8221;分隔，说明这是同一个函数的定义。函数式编程语言中，这种定义方式很常见，看起来形式很整齐，宛如数学公式。 <br><br>这段代码的含义是，当参数值等于0的时候，那么，程序走第一个函数定义分支（即分号&#8220;;&#8221;结尾的&#8220;times10( 0 ) &#8211;&gt; 1;&#8221;），否则，走下面的函数定义分支（即&#8220;times10( Number ) &#8211;&gt;&#8230;&#8221;）。 <br><br>第二个分支中的参数不是一个常数，而是一个变量Number，表示这个分支可以接受任何除了0之外的参数值，比如，1、2、12等等，这些值将赋给变量Number。 <br>因此，这个地方也体现了Pattern Match的第二个功能——变量赋值。 <br><br>Pattern Match的形式可以很复杂，下面举几个典型的例子。 <br>（1）数据结构拆解赋值 <br>前面将到了ErLang语言有一种相当于定长数组的Tuple类型，我们可以很方便地根据元素的位置进行并行赋值。比如， <br>{First, Second} = {1, 2} <br>我们还可以对复合Tuple数据结构进行赋值，比如 <br>{A, {B, C}, D} = { 1, {2, 3}, 4 } <br>List数据结构的赋值也是类似。由于List的写法和用法不是那么简单，三言两语也说不清楚，还徒增困扰，这里不再赘述。 <br>（2）assertEquals语句 <br>在Java等语言中，我们写单元测试的时候，会写一些assert语句，验证程序运行结果。这些assert语句通常是以API的方式提供，比如，assertTrue()、assertEquals()等。 <br>在ErLang中，可以用简单的语句达到类似于assertTrue()、assertEquals()等API的效果。 <br>比如，ErLang中，true = testA() 这样的语句表示testA的返回结果必须是true，否则就会抛出异常。这个用法很巧妙。这里解释一下。 <br>前面讲过，ErLang语法约定，小写字母开头的名字，都是常量名。这里的true自然也是一个常量，既然是常量，我们不可能对它赋值，那么true = testA()的意思就不是赋值，而是进行匹配比较。 <br>（3）匹配和赋值同时进行 <br>我们来看这样一段代码。 <br>case Result of <br>{ok, Message} -&gt; save(Message); <br>{error, ErrorMessage} -&gt; log(ErrorMessage) <br>end. <br><br>这段代码中，Result是一个Tuple类型，包含两个元素，第一个元素表示成功（ok）或者失败（error），第二个元素表示具体的信息。 <br>可以看到，这两个条件分支中，同时出现了常量和变量。第一个条件分支中的ok是常量，Message是变量；第二个条件分支中的error是常量，ErrorMessage是变量。 <br>这两个条件分支都既有比较判断，也有变量赋值。首先，判断ResultTuple中的第一个元素和哪一个分支的第一个元素匹配，如果相配，那么把ResultTuple中的第二个元素赋给这个分支的第二个变量元素。即，如果Result的第一个元素是ok，那么走第一个条件分支，并且把Result的第二个元素赋给Message变量；如果Result的第二个元素是error，那么走第二个条件分支，并且把Result的第二个元素赋给ErrorMessage变量。 <br><br>在Java等语言中，实现上述的条件分支逻辑，则需要多写几条语句ErLang语法可以从形式上美化和简化逻辑分支分派复杂的程序。 <br>除了支持数相等比较，Pattern Match还可以进行范围比较、大小比较等，需要用到关键字when，不过用到when的情况，就比if else简洁不了多少，这里不再赘述。 <br>匿名函数 <br>ErLang允许在一个函数体内部定义另一个匿名函数，这是函数式编程的最基本的功能。这样，函数式语言才可以支持Closure。我们来看一个ErLang的匿名函数的例子。 <br>outer( C ) &#8211;&gt; <br>Inner = fun(A, B) -&gt; A + B + C end, <br>Inner(2, 3). <br><br>这段代码首先定义了一个命名函数outer，然后在outer函数内部定义了一个匿名函数。可以看到，这个匿名函数采用关键字fun来定义。前面讲过，函数式编程的函数就相当于面向对象编程的类实例对象，匿名函数自然也是这样，也相当于类实例，我们可以把这个匿名函数赋给一个变量Inner，然后我们还可以把这个变量当作函数来调用，比如，Inner(2, 3)。 <br>fun是ErLang用来定义匿名函数的关键字。这个关键字很重要。fun定义匿名函数的用法不是很复杂，和命名函数定义类似。 <br>函数分支的定义也是类似，只是需要用end结尾，而不是用句号&#8220;.&#8221;结尾，而且fun只需要写一次，不需要向命名函数那样，每个分支都要写。比如， <br>MyFunction = fun(0) -&gt; 0; <br>(Number) -&gt; Number * 10 + 1 end, <br>MyFunction(3), <br>函数作为变量 <br>匿名函数可以当作对象赋给变量，命名函数同样也可以赋给变量。具体用法还是需要借助重要的fun关键字。比如， <br>MyFunction = fun outer / 1 <br><br>就可以把上述定义的outer函数赋给MyFunction变量。后面的 / 0表示这个outer函数只有一个参数。因为ErLang允许有多个同名函数的定义，只要参数个数不同，就是不同的函数。 <br>我们可以看到，任何函数都可以作为变量，也可以作为参数和返回值传来传去，这些变量也可以随时作为函数进行调用，于是就具有了一定的动态性。 <br>函数的动态调用 <br>ErLang有一个apply函数，可以动态调用某一个函数变量。 <br>基本用法是 apply( 函数变量，函数参数列表 )。比如，上面的MyFunciton函数变量，就可以这么调用，apply( MyFunction, [ 5 ])。 <br>那么我们能否根据一个字符串作为函数名获取一个函数变量呢？这样我们就可以根据一个字符串来动态调用某个函数了。 <br>ErLang中，做到这一点很简单。前面讲过，函数名一旦定义了，自然就固定了，这也类似于常量名，属于不可变的atom（原子）。所有的atom都可以转换成字符串，也可以从字符串转换过来。ErLang中的字符串实质上都是List。字符串和atom之间的转换通过list_to_atom和atom_to_list来转换。 <br>于是我们可以这样获取MyFunciton：MyFunction = list_to_atom(&#8220;outer&#8221;) <br>如果outer函数已经定义，那么MyFucntion就等于outer函数，如果outer函数没有定义，那么list_to_atom(&#8220;outer&#8221;)会产生一个新的叫做outer的atom，MyFucntion就等于这个新产生的atom。 <br>如果需要强制产生一个已经存在的atom，那么我们需要调用list_to_existing_atom转换函数，这个函数不会产生新的atom，而是返回一个已经存在了的atom。 <br>Tuple作为数据成员集合 <br>前面讲解函数式编程特性的时候，提到了函数式编程没有面向对象编程的成员变量，这是一个限制。 <br>ErLang的Tuple类型可以一定程度克服这个限制。Tuple可以一定程度上担当容纳成员变量的职责。 <br>面向对象的类定义，其实就是一群数据和函数的集合，只是集合的成员之间都有一个this指针相关联，可以相互找到。 <br>ErLang的Tuple类型就是数据的集合，可以很自然地发挥成员变量的作用，比如，{Member1, Member2}。 <br>读者可能会说，ErLang的函数也可以作为变量，也可以放到Tuple里面，比如， { Memer1, Member2, Funtion1, Function2}。这不就和面向对象编程一样了吗？ <br>遗憾的是，这样做是得不偿失的。因为函数式编程没有面向对象的那种内在的this指针支持，自然也没有内在的多态和继承支持，硬把数据和函数糅合在一个Tuple里面，一点好处都没有，而且还丧失了函数作为实例对象的灵活性。 <br>所以，函数式编程的最佳实践（Best Practice）应该是：Tuple用来容纳成员数据，函数操作Tuple。Tuple定义和函数定义加在一起，就构成了松散的数据结构，功能上类似于面向对象的类定义。Tuple + 函数的数据结构，具有多态的特性，因为函数本身能够作为变量替换；但是不具有继承的特性，因为没有this指针的内在支持。 <br>正是因为Tuple在数据类型构造方面的重大作用，所以，ErLang专门引入了一种叫做Record的宏定义，可以对Tuple的数组下标位置命名。比如，把第一个元素叫做Address，第二个元素叫做Zipcode，这样程序员就可以这些名字访问Tuple里面的元素，而不需要按照数组下标位置来访问。 <br>Tuple和Record的具体用法还是有一定复杂度，限于篇幅，本章没有展开说明，只提了一些原理方面的要点。 <br>其它 <br>ErLang还有其它语法特性和细节，不再一一赘述。有兴趣的读者，可以自行去ErLang网站（www.erlang.org）进行研究。 
<img src ="http://www.cppblog.com/keigoliye/aggbug/95894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-11 11:04 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/11/95894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门（五）——补遗</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/11/95888.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 11 Sep 2009 02:16:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/11/95888.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/95888.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/11/95888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/95888.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/95888.html</trackback:ping><description><![CDATA[<span style="FONT-WEIGHT: bold">1。Erlang的保留字</span>有：<br>
<p>after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor<a name=1.6><!----></a> </p>
基本都是些用于逻辑运算、位运算以及特殊表达式的符号<br><br><span style="FONT-WEIGHT: bold">2.Erlang的类型</span>，除了在前面入门一提到的类型外，还包括：<br>1)Binary，用于表示某段未知类型的内存区域<br>比如：<br>1&gt; <strong>&lt;&lt;10,20&gt;&gt;.</strong> <br>&lt;&lt;10,20&gt;&gt; <br>2&gt; <strong>&lt;&lt;"ABC"&gt;&gt;.</strong><br>&nbsp;&lt;&lt;65,66,67&gt;&gt; <br><br>2）Reference，通过调用mk_ref/0产生的运行时的unique term<br><br>3)String，字符串，Erlang中的字符串用双引号包括起来，其实也是list。编译时期，两个邻近的字符串将被连接起来，比如"string" "42" 等价于 "string42"<br><br>4)Record，记录类型，与c语言中的struct类似，模块可以通过-record属性声明，比如：<br>-module(person). <br>-export([new/2]).<br>-record(person, {name, age}). <br>new(Name, Age) -&gt;<br>&nbsp; &nbsp;&nbsp; #person{name=Name, age=Age}. <br>1&gt; <strong>person:new(dennis, 44).</strong> <br>{person,dennis,44} <br>&nbsp;在编译后其实已经被转化为tuple。可以通过Name#person.name来访问Name Record的name属性。<br><br><span style="FONT-WEIGHT: bold">3.模块的预定义属性</span>：<br><code>-module(Module).</code>&nbsp;&nbsp;&nbsp; 声明模块名称，必须与文件名相同<br><code>-export(Functions).</code>&nbsp;&nbsp; 指定向外界导出的函数列表<br><code>-import(Module,Functions).</code>&nbsp;&nbsp; 引入函数，引入的函数可以被当作本地定义的函数使用<br><code>-compile(Options).</code>&nbsp;&nbsp;&nbsp;&nbsp; 设置编译选项，比如export_all<br>-vsn(Vsn).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 模块版本，设置了此项，可以通过<code>beam_lib:version/1</code> 获取此项信息<br>可以通过-include和-include_lib来包含文件，两者的区别是include-lib不能通过绝对路径查找文件，而是在你当前Erlang的lib目录进行查找。<br><br><span style="FONT-WEIGHT: bold">4.try表达式</span>，try表达式可以与catch结合使用，比如：<br>
<pre>try Expr<br>catch<br>    throw:Term -&gt; Term;<br>    exit:Reason -&gt; {'EXIT',Reason}<br>    error:Reason -&gt; {'EXIT',{Reason,erlang:get_stacktrace()}}<br>end<br><br>不仅如此，try还可以与after结合使用，类似java中的try..finally，用于进行清除作用，比如：<br>termize_file(Name) -&gt;<br>{ok,F} = file:open(Name, [read,binary]),<br>try<br>{ok,Bin} = file:read(F, 1024*1024),<br>binary_to_term(Bin)<br>after<br>file:close(F)<br>end.<br><br><br><span style="FONT-WEIGHT: bold">5.列表推断</span>（List Comprehensions），函数式语言特性之一，Erlang中的语法类似：<br>[Expr || Qualifier1,...,QualifierN]<br>Expr可以是任意的表达式，而Qualifier是generator或者filter。还是各举例子说明下。<br>1&gt; <strong> [X*2 || X &lt;- [1,2,3]].</strong><br>[2,4,6]<br><br>2&gt; L=[1,2,3,4,5,6,7].<br>[1,2,3,4,5,6,7]<br><br>
<pre>3&gt; <span style="FONT-WEIGHT: bold">[X|X&lt;-L,X&gt;=3].</span><br>[3,4,5,6,7]<br><br>
<pre>再看几个比较酷的例子，来自Programming <a title="" href="http://www.erlang.org/"><u><font color=#000000>Erlang</font></u></a>，<br>比如<span style="FONT-WEIGHT: bold">快速排序</span>：<br>-module(qsort).<br>-export([qsort/1]).<br>qsort([])-&gt;[];<br>qsort([Pivot|T])-&gt;<br>&nbsp; qsort([X||X&lt;-T,X</pre>
<br>
<br>
<span style="FONT-WEIGHT: bold">6.宏</span>，定义常量或者函数等等，语法如下：<br>
-define(Const, Replacement).<br>
-define(Func(Var1,...,VarN), Replacement).<br>
<br>
使用的时候在宏名前加个问号？，比如?Const，Replacement将插入宏出现的位置。系统预定义了一些宏:<br>
<code><span style="FONT-WEIGHT: bold">?MODULE </span>  表示当前模块名<br>
<br>
<span style="FONT-WEIGHT: bold">?MODULE_STRING</span> 同上，但是以字符串形式<br>
</code><span style="FONT-WEIGHT: bold">?FILE</span>    当前模块的文件名<br>
<span style="FONT-WEIGHT: bold">?LINE</span>    调用的当前代码行数<br>
<span style="FONT-WEIGHT: bold">?MACHINE</span>  机器名<br>
<br>
Erlang的宏与C语言的宏很相似，同样有宏指示符，包括：<br>
<dl><dt><code>-undef(Macro).</code> <dd>取消宏定义<br>
<dt><code>-ifdef(Macro).</code> <dd>当宏Macro有定义的时候，执行以下代码<br>
<dt><code>-ifndef(Macro).</code> <dd>同上，反之<br>
<dt><code>-else.</code> <dd>接在ifdef或者ifndef之后，表示不满足前者条件时执行以下代码<br>
<br>
<dt><code>-endif.</code> <dd>if终止符</dd></dl>假设宏-define(Square(X),X*X).用于计算平方，那么??X将返回X表达式的字符串形式，类似C语言中#arg<br>
<br>
一个简单的宏例子：<br>
<div class=code_title>ruby 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-rb>
    <li class=alt><span><span>-</span><span class=keyword><strong><font color=#7f0055>module</font></strong></span><span>(macros_demo).&nbsp;&nbsp;</span></span>
    <li class=""><span>-ifdef(debug).&nbsp;&nbsp;</span>
    <li class=alt><span>-define(LOG(X),&nbsp;io<span class=symbol>:format</span><span>(</span><span class=string><font color=#0000ff>"{~p,~p}:&nbsp;~p~n"</font></span><span>,&nbsp;[?MODULE,?LINE,X])).&nbsp;&nbsp;</span></span>
    <li class=""><span>-<span class=keyword><strong><font color=#7f0055>else</font></strong></span><span>.&nbsp;&nbsp;</span></span>
    <li class=alt><span>-define(LOG(X),&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>).&nbsp;&nbsp;</span></span>
    <li class=""><span>-endif.&nbsp;&nbsp;</span>
    <li class=alt><span>-define(Square(X),X*X).&nbsp;&nbsp;</span>
    <li class=""><span>-compile(export_all).&nbsp;&nbsp;</span>
    <li class=alt><span>test()-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;A=3,&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;?LOG(A),&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;B=?Square(A),&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;io<span class=symbol>:format</span><span>(</span><span class=string><font color=#0000ff>"square(~w)&nbsp;is&nbsp;~w~n"</font></span><span>,[A,B]).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>
当编译时不开启debug选项的时候：<br>
17&gt; c(macros_demo).<br>
{ok,macros_demo}<br>
18&gt; macros_demo:test().<br>
square(3) is 9<br>
<br>
当编译时开启debug之后：<br>
<br>
19&gt; c(macros_demo,{d,debug}).<br>
{ok,macros_demo}<br>
20&gt; macros_demo:test().<br>
<span style="FONT-WEIGHT: bold">{macros_demo,11}: 3</span><br>
square(3) is 9<br>
ok<br>
<br>
可以看到LOG的输出了，行数、模块名以及参数<br>
<br>
7、<span style="FONT-WEIGHT: bold">Process Dictionary</span>，每个进程都有自己的process dictionary，用于存储这个进程内的全局变量，可以通过下列<br>
BIFs操作：<br>
put(Key, Value)<br>
get(Key)<br>
get()<br>
get_keys(Value)<br>
erase(Key)<br>
erase()<br>
<br>
<span style="FONT-WEIGHT: bold">8、关于分布式编程</span>，需要补充的几点<br>
1）节点之间的连接默认是transitive，也就是当节点A连接了节点B，节点B连接了节点C，那么节点A也与节点C互相连接<br>
可以通过启动节点时指定参数-connect_all false来取消默认行为<br>
<br>
2）隐藏节点，某些情况下，你希望连接一个节点而不去连接其他节点，你可以通过在节点启动时指定-hidden选项<br>
来启动一个hidden node。在此情况下，通过nodes()查看所有连接的节点将不会出现隐藏的节点，想看到隐藏的节点<br>
可以通过nodes(hidden)或者nodes(connected)来查看。<br>
<br>
完整的erl选项如下：<br>
<br>
<table cellSpacing=0 cellPadding=2 border=1>
    <tbody>
        <tr>
            <td vAlign=center align=left><code>-connect_all false</code> </td>
            <td vAlign=center align=left>上面已经解释。 </td>
        </tr>
        <tr>
            <td vAlign=center align=left><code>-hidden</code> </td>
            <td vAlign=center align=left>启动一个hidden node<br></td>
        </tr>
        <tr>
            <td vAlign=center align=left><code>-name Name</code> </td>
            <td vAlign=center align=left>启动一个系统成为节点，使用long name. </td>
        </tr>
        <tr>
            <td vAlign=center align=left><code>-setcookie Cookie</code> </td>
            <td vAlign=center align=left>与<code><a title="" href="http://www.erlang.org/"><u><font color=#000000>Erlang</font></u></a>:set_cookie(node(), Cookie)</code>.相同，设置magic cookie<br></td>
        </tr>
        <tr>
            <td vAlign=center align=left><code>-sname Name</code> </td>
            <td vAlign=center align=left>启动一个Erlang系统作为节点，使用short name <br></td>
        </tr>
    </tbody>
</table>
<br>
<br>
注意,<span style="FONT-WEIGHT: bold">short name启动的节点是无法与long name节点通信的</span>。<br>
<br>
<pre><span style="FONT-WEIGHT: bold">.一个小细节，在Erlang中小于等于是用=&lt;表示，而不是一般语言中的&lt;=语法，我犯过错误的地方，同样，不等于都是用/号，而不是</span><br style="FONT-WEIGHT: bold"><span style="FONT-WEIGHT: bold">!,比如/=、=/=。</span><br><br><span style="FONT-WEIGHT: bold">10.and or 和andalso orelse的区别</span><br><br>and和or会计算两边的表达式，而andalso和orelse的求值采用短路机制，比如exp1 andalso exp2，当exp1返回false之后，就不会去求值<br>exp2，而是直接返回false，而exp1 and exp2会对exp1和exp2都进行求值，or与orelse也类似。</pre>
</pre>
</pre>
<img src ="http://www.cppblog.com/keigoliye/aggbug/95888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-11 10:16 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/11/95888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门（三）——分布式编程</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/11/95886.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 11 Sep 2009 02:13:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/11/95886.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/95886.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/11/95886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/95886.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/95886.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 所谓分布式的Erlang应用是运行在一系列Erlang节点组成的网络之上。这样的系统的性质与单一节点上的Erlang系统并没有什么不同。分布式这是个&#8220;大词&#8221;，Erlang从语言原生角度支持分布式编程，相比于java简单不少。<br>一、分布式机制<br>下列的BIFs是用于分布式编程：<br><span style="FONT-WEIGHT: bold">spawn(Node, Mod, Func, Args)</span><br>启动远程节点的一个进程<br><br><span style="FONT-WEIGHT: bold">spawn_link(Node, Mod, Func, Args)</span><br>启动远程节点的一个进程并创建连接到该进程<br><br><span style="FONT-WEIGHT: bold">monitor_node(Node, Flag)</span><br>如果Flag是true,这个函数将使调用（该函数）的进程可以监控节点Node。如果节点已经舍弃或者并不存在，调用的进程将收到一个{nodedown,Node}的消息。如果Flag是false,监控将被关闭<br><br><span style="FONT-WEIGHT: bold">node()</span><br>返回我们自己的进程name<br><br><span style="FONT-WEIGHT: bold">nodes()</span><br>返回其他已知的节点name列表<br><br><span style="FONT-WEIGHT: bold">node(Item)</span><br>返回原来Item的节点名称，Item可以是Pid,引用（reference）或者端口(port)<br><br><span style="FONT-WEIGHT: bold">disconnect_node(Nodename)</span><br>从节点Nodename断开。<br><br>&nbsp; &nbsp; 节点是分布式Erlang的核心概念。在一个分布式Erlang应用中，术语（term)节点(node）意味着一个可以加入分布式 transactions的运行系统。通过一个称为net kernal的特殊进程，一个独立的Erlang系统可以成为一个分布式Erlang系统的一部分。当net kernal进程启动的时候，我们称系统是alive的。<br><br>&nbsp; &nbsp; 与远程节点上的进程进行通信，与同一节点内的进程通信只有一点不同：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>{Name,&nbsp;Node}&nbsp;!&nbsp;Mess.&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
&nbsp;&nbsp; <br>显然，需要接收方增加一个参数Node用于指定接受进程所在的节点。节点的name一般是用@隔开的atom类型，比如pong@dennis，表示计算机名为dennis上的pong节点。通过执行:<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>erl&nbsp;-sname&nbsp;pong&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>将在执行的计算机中创建一个节点pong。为了运行下面的例子，你可能需要两台计算机，如果只有一台，只要同时开两个Erlang系统并以不同的节点名称运行也可以。<br><br>二、一些例子。<br>&nbsp;&nbsp;&nbsp; 这个例子完全来自上面提到的翻译的连接，关于分布式编程的章节。我增加了截图和说明。<br>首先是代码：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(tut17).&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>-export([start_ping/<span class=number>1</span><span>,&nbsp;start_pong/</span><span class=number>0</span><span>,&nbsp;&nbsp;ping/</span><span class=number>2</span><span>,&nbsp;pong/</span><span class=number>0</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>ping(<span class=number>0</span><span>,&nbsp;Pong_Node)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{pong,&nbsp;Pong_Node}&nbsp;!&nbsp;finished,&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"ping&nbsp;finished~n"</font></span><span>,&nbsp;[]);&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>ping(N,&nbsp;Pong_Node)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{pong,&nbsp;Pong_Node}&nbsp;!&nbsp;{ping,&nbsp;self()},&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pong&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Ping&nbsp;received&nbsp;pong~n"</font></span><span>,&nbsp;[])&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;end,&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;ping(N&nbsp;-&nbsp;<span class=number>1</span><span>,&nbsp;Pong_Node).&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>pong()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finished&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Pong&nbsp;finished~n"</font></span><span>,&nbsp;[]);&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ping,&nbsp;Ping_PID}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Pong&nbsp;received&nbsp;ping~n"</font></span><span>,&nbsp;[]),&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ping_PID&nbsp;!&nbsp;pong,&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pong()&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>start_pong()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;register(pong,&nbsp;spawn(tut17,&nbsp;pong,&nbsp;[])).&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>start_ping(Pong_Node)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;spawn(tut17,&nbsp;ping,&nbsp;[<span class=number>3</span><span>,&nbsp;Pong_Node]).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>&nbsp;&nbsp;&nbsp; 代码是创建两个相互通信的进程，相互发送消息并通过io显示在屏幕上，本来是一个单一系统的例子，现在我们让两个进程运行在不同的两个节点上。注意 start_ping方法，创建的进程调用ping方法，ping方法有两个参数，一个是发送消息的次数，一个就是远程节点的name了，也就是我们将要 创建的进程pong的所在节点。start_pong创建一个调用函数pong的进程，并注册为名字pong（因此在ping方法中可以直接发送消息给 pong)。<br>&nbsp;&nbsp;&nbsp; 我是在windows机器上测试，首先打开两个cmd窗口，并cd到Erlang的安装目录下的bin目录，比如C:\Program Files\erl5.5.3\bin,将上面的程序存为tut17.erl，并拷贝到同一个目录下。我们将创建两个节点，一个叫 ping@dennis,一个叫pong@dennis,其中dennis是我的机器名。见下图：<br><img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/d-erlang1.jpg" border=0><br>采用同样的命令<br><span style="COLOR: rgb(0,0,0)"><br>erl&nbsp;</span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">sname&nbsp;ping</span><br><br>创建ping节点。然后在pong节点下执行start_pong()：<br><img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/d-erlang2.jpg" border=0><br><br>OK,这样就在节点pong上启动了pong进程，然后在ping节点调用start_ping，传入参数就是pong@dennis<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>tut17:start_ping(pong</span><span class=annotation>@dennis</span><span>).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>执行结果如下图：<br><img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/d-erlang3.jpg" border=0><br>同样在pong节点上也可以看到：<br><img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/d-erlang4.jpg" border=0><br><br>&nbsp;&nbsp;&nbsp; 结果如我们预期的那样，不同节点上的两个进程相互通信如此简单。我们给模块tut17增加一个方法，用于启动远程进程，也就是调用spawn(Node,Module,Func,Args)方法：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>start(Ping_Node)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;register(pong,&nbsp;spawn(tut17,&nbsp;pong,&nbsp;[])),&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;spawn(Ping_Node,&nbsp;tut17,&nbsp;ping,&nbsp;[<span class=number>3</span><span>,&nbsp;node()]).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>pong进程启动Ping_Node节点上的进程ping。具体结果不再给出。<br>
<img src ="http://www.cppblog.com/keigoliye/aggbug/95886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-11 10:13 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/11/95886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门（四）——错误处理和鲁棒性</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/11/95887.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 11 Sep 2009 02:13:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/11/95887.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/95887.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/11/95887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/95887.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/95887.html</trackback:ping><description><![CDATA[&nbsp; 任何一门语言都有自己的错误处理机制，Erlang也不例外，语法错误编译器可以帮你指出，而逻辑错误和运行时错误就只有靠程序员利用Erlang提供的机制来妥善处理，放置程序的崩溃。<br>&nbsp;&nbsp;&nbsp; Erlang的机制有：<br>1)监控某个表达式的执行<br>2）监控其他进程的行为<br>3）捕捉未定义函数执行错误等<br><br><span style="FONT-WEIGHT: bold">一、catch和throw语句</span><br>&nbsp;&nbsp;&nbsp; 调用某个会产生错误的表达式会导致调用进程的非正常退出，比如错误的模式匹配（2=3），这种情况下可以用catch语句：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(0,0,0)">catch&nbsp;expression</span><br>&nbsp;&nbsp;&nbsp; 试看一个例子，一个函数foo：<br><br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>foo(</span><span class=number>1</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>hello;&nbsp;&nbsp;</span>
    <li class=alt><span>foo(<span class=number>2</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>throw</font></strong></span><span>({myerror,&nbsp;abc});&nbsp;&nbsp;</span></span>
    <li class=alt><span>foo(<span class=number>3</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>tuple_to_list(a);&nbsp;&nbsp;</span>
    <li class=alt><span>foo(<span class=number>4</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>exit({myExit,&nbsp;<span class=number>222</span><span>}).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>当没有使用catch的时候，假设有一个标识符为Pid的进程调用函数foo（在一个模块中），那么：<br>foo(1) - 返回hello<br>foo(2) - 语句throw({myerror, abc})执行，因为我们没有在一个catch中调用foo(2),因此进程Pid将因为错误而终止。<br><br>foo(3) - tuple_to_list将一个元组转化为列表，因为a不是元组，因此进程Pid同样因为错误而终止<br><br>foo(4) - 因为没有使用catch，因此foo(4)调用了exit函数将使进程Pid终止，{myExit, 222} 参数用于说明退出的原因。<br><br>foo(5) - 进程Pid将因为foo(5)的调用而终止，因为没有和foo(5)匹配的函数foo/1。<br><br>&nbsp;&nbsp;&nbsp; 让我们看看用catch之后是什么样：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>demo(X)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>case</font></strong></span><span>&nbsp;</span><span class=keyword><strong><font color=#7f0055>catch</font></strong></span><span>&nbsp;foo(X)&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;{myerror,&nbsp;Args}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{user_error,&nbsp;Args};&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;{'EXIT',&nbsp;What}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{caught_error,&nbsp;What};&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;Other&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Other&nbsp;&nbsp;</span>
    <li class=alt><span>end.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>再看看结果，<br>demo(1) - 没有错误发生，因此catch语句将返回表达式结果hello<br>demo(2) - foo(2)抛出错误{myerror,&nbsp;abc}，被catch返回，因此将返回{user_error,abc}<br><br>demo(3) - foo(3)执行失败，因为参数错误，因此catch返回{'EXIT',badarg'},最后返回{caught_error,badarg}<br><br>demo(4) - 返回{caught_error,{myexit,222}}<br>demo(5) - 返回{caught_error,function_clause}<br><br>&nbsp;&nbsp;&nbsp; 使用catch和throw可以将可能产生错误的代码包装起来，throw可以用于尾递归的退出等等。Erlang是和scheme一样进行尾递归优化的，它们都没有显式的迭代结构（比如for循环）<br><br><span style="FONT-WEIGHT: bold">二、进程的终止</span><br>&nbsp;&nbsp;&nbsp; 在进程中调用exit的BIFs就可以显式地终止进程，exit(normal)表示正常终止，exit(Reason)通过Reason给出非正常终止的原因。进程的终止也完全有可能是因为运行时错误引起的。<br><br><span style="FONT-WEIGHT: bold">三、连接的进程</span><br>&nbsp;&nbsp;&nbsp; 进程之间的连接是双向的，也就是说进程A打开一个连接到B,也意味着有一个从B到A的连接。当进程终止的时候，有一个EXIT信号将发给所有与它连接的进程。信号的格式如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {'EXIT', Exiting_Process_Id, Reason} <br>Exiting_Process_Id 是指终止的进程标记符<br>Reason 是进程终止的原因。如果Reason是normal，接受这个信号的进程的默认行为是忽略这个信号。默认对Exit信号的处理可以被重写，以允许进程对Exit信号的接受做出不同的反应。<br>1.连接进程：<br>通过link(Pid)，就可以在调用进程与进程Pid之间建立连接<br>2.取消连接<br>反之通过unlink(Pid)取消连接。 <br>3.创立进程并连接：<br>通过spawn_link(Module, Function, ArgumentList)创建进程并连接，该方法返回新创建的进程Pid<br><br>&nbsp;&nbsp;&nbsp; 通过进程的相互连接，许多的进程可以组织成一个网状结构，EXIT信号（非normal)从某个进程发出（该进程终止），所有与它相连的进程以及与这些进 程相连的其他进程，都将收到这个信号并终止，除非它们实现了自定义的EXIT信号处理方法。一个进程链状结构的例子：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(normal).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([start/<span class=number>1</span><span>,&nbsp;p1/</span><span class=number>1</span><span>,&nbsp;test/</span><span class=number>1</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>start(N)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>register(start,&nbsp;spawn_link(normal,&nbsp;p1,&nbsp;[N&nbsp;-&nbsp;<span class=number>1</span><span>])).&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;p1(<span class=number>0</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;top1();&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;p1(N)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;top(spawn_link(normal,&nbsp;p1,&nbsp;[N&nbsp;-&nbsp;<span class=number>1</span><span>]),N).&nbsp;&nbsp;</span></span>
    <li class=alt><span>top(Next,&nbsp;N)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>receive&nbsp;&nbsp;</span>
    <li class=alt><span>X&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>Next&nbsp;!&nbsp;X,&nbsp;&nbsp;</span>
    <li class=alt><span>io:format(<span class=string><font color=#0000ff>"Process&nbsp;~w&nbsp;received&nbsp;~w~n"</font></span><span>,&nbsp;[N,X]),&nbsp;&nbsp;</span></span>
    <li class=""><span>top(Next,N)&nbsp;&nbsp;</span>
    <li class=alt><span>end.&nbsp;&nbsp;</span>
    <li class=""><span>top1()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>receive&nbsp;&nbsp;</span>
    <li class=""><span>stop&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>io:format(<span class=string><font color=#0000ff>"Last&nbsp;process&nbsp;now&nbsp;exiting&nbsp;~n"</font></span><span>,&nbsp;[]),&nbsp;&nbsp;</span></span>
    <li class=""><span>exit(finished);&nbsp;&nbsp;</span>
    <li class=alt><span>X&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>io:format(<span class=string><font color=#0000ff>"Last&nbsp;process&nbsp;received&nbsp;~w~n"</font></span><span>,&nbsp;[X]),&nbsp;&nbsp;</span></span>
    <li class=alt><span>top1()&nbsp;&nbsp;</span>
    <li class=""><span>end.&nbsp;&nbsp;</span>
    <li class=alt><span>test(Mess)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>start&nbsp;!&nbsp;Mess.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>执行：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>&gt;&nbsp;normal:start(</span><span class=number>3</span><span>).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>&gt;&nbsp;normal:test(<span class=number>123</span><span>).&nbsp;&nbsp;</span></span>
    <li class=""><span>Process&nbsp;<span class=number>2</span><span>&nbsp;received&nbsp;</span><span class=number>123</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>Process&nbsp;<span class=number>1</span><span>&nbsp;received&nbsp;</span><span class=number>123</span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>Last&nbsp;process&nbsp;received&nbsp;<span class=number>123</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>&gt;&nbsp;normal:test(stop).&nbsp;&nbsp;</span>
    <li class=alt><span>Process&nbsp;<span class=number>2</span><span>&nbsp;received&nbsp;stop&nbsp;&nbsp;</span></span>
    <li class=""><span>Process&nbsp;<span class=number>1</span><span>&nbsp;received&nbsp;stop&nbsp;&nbsp;</span></span>
    <li class=alt><span>Last&nbsp;process&nbsp;now&nbsp;exiting&nbsp;&nbsp;</span>
    <li class=""><span>stop&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br><span style="FONT-WEIGHT: bold">四、运行时失败</span><br>&nbsp;&nbsp;&nbsp; 一个运行时错误将导致进程的非正常终止，伴随着非正常终止EXIT信号将发出给所有连接的进程，EXIT信号中有Reason并且Reason中包含一个atom类型用于说明错误的原因，常见的原因如下：<br><br><span style="FONT-WEIGHT: bold">badmatch</span> - 匹配失败，比如一个进程进行1=3的匹配，这个进程将终止，并发出{'EXIT', From, badmatch}信号给连接的进程<br><br><span style="FONT-WEIGHT: bold">badarg</span>&nbsp; - 顾名思义，参数错误，比如atom_to_list(123),数字不是atom，因此将发出{'EXIT', From, badarg}信号给连接进程<br><br><span style="FONT-WEIGHT: bold">case_clause</span> - 缺少分支匹配，比如<br>&nbsp;&nbsp;&nbsp; <br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>M&nbsp;=&nbsp;</span><span class=number>3</span><span>,&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>case</font></strong></span><span>&nbsp;M&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;<span class=number>1</span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;yes;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;<span class=number>2</span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;no&nbsp;&nbsp;</span>
    <li class=alt><span>end.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>没有分支3，因此将发出{'EXIT', From, case_clause}给连接进程<br><br><span style="FONT-WEIGHT: bold">if_clause</span> - 同理，if语句缺少匹配分支<br><br><span style="FONT-WEIGHT: bold">function_clause</span> - 缺少匹配的函数，比如：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>foo(</span><span class=number>1</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;yes;&nbsp;&nbsp;</span>
    <li class=alt><span>foo(<span class=number>2</span><span>)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;no.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>如果我们调用foo(3)，因为没有匹配的函数，将发出{'EXIT', From, function_clause} 给连接的进程。<br><br><span style="FONT-WEIGHT: bold">undef</span> - 进程执行一个不存在的函数<br><br><span style="FONT-WEIGHT: bold">badarith</span> - 非法的算术运算，比如1+foo。<br><br><span style="FONT-WEIGHT: bold">timeout_value</span> - 非法的超时时间设置，必须是整数或者infinity<br><br><span style="FONT-WEIGHT: bold">nocatch</span> - 使用了throw，没有相应的catch去通讯。<br><br><span style="FONT-WEIGHT: bold">五、修改默认的信号接收action</span><br>&nbsp;&nbsp; 当进程接收到EXIT信号，你可以通过process_flag/2方法来修改默认的接收行为。执行process_flag(trap_exit, true)设置捕获EXIT信号为真来改变默认行为，也就是将EXIT信号作为一般的进程间通信的信号进行接受并处理；process_flag (trap_exit,false)将重新开启默认行为。<br>&nbsp;&nbsp; 例子：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(link_demo).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([start/<span class=number>0</span><span>,&nbsp;demo/</span><span class=number>0</span><span>,&nbsp;demonstrate_normal/</span><span class=number>0</span><span>,&nbsp;demonstrate_exit/</span><span class=number>1</span><span>,&nbsp;&nbsp;</span></span>
    <li class=alt><span>demonstrate_error/<span class=number>0</span><span>,&nbsp;demonstrate_message/</span><span class=number>1</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=""><span>start()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;register(demo,&nbsp;spawn(link_demo,&nbsp;demo,&nbsp;[])).&nbsp;&nbsp;</span>
    <li class=""><span>demo()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;process_flag(trap_exit,&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>),&nbsp;&nbsp;</span></span>
    <li class=""><span>demo1().&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;demo1()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;{'EXIT',&nbsp;From,&nbsp;normal}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Demo&nbsp;process&nbsp;received&nbsp;normal&nbsp;exit&nbsp;from&nbsp;~w~n"</font></span><span>,[From]),&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;demo1();&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{'EXIT',&nbsp;From,&nbsp;Reason}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Demo&nbsp;process&nbsp;received&nbsp;exit&nbsp;signal&nbsp;~w&nbsp;from&nbsp;~w~n"</font></span><span>,[Reason,&nbsp;From]),&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;demo1();&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;finished_demo&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Demo&nbsp;finished&nbsp;~n"</font></span><span>,&nbsp;[]);&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;Other&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Demo&nbsp;process&nbsp;message&nbsp;~w~n"</font></span><span>,&nbsp;[Other]),&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;demo1()&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;end.&nbsp;&nbsp;</span>
    <li class=alt><span>demonstrate_normal()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;link(whereis(demo)).&nbsp;&nbsp;</span>
    <li class=alt><span>demonstrate_exit(What)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;link(whereis(demo)),&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;exit(What).&nbsp;&nbsp;</span>
    <li class=""><span>demonstrate_message(What)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;demo&nbsp;!&nbsp;What.&nbsp;&nbsp;</span>
    <li class=""><span>demonstrate_error()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;link(whereis(demo)),&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;<span class=number>1</span><span>&nbsp;=&nbsp;</span><span class=number>2</span><span>.&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>&nbsp;&nbsp;&nbsp; 创建的进程执行demo方法，demo方法中设置了trap_exit为true,因此，在receive中可以像对待一般的信息一样处理EXIT信号，这个程序是很简单了，测试看看：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>&gt;&nbsp;link_demo:start().&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>&gt;&nbsp;link_demo:demonstrate_normal().&nbsp;&nbsp;</span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>Demo&nbsp;process&nbsp;received&nbsp;normal&nbsp;exit&nbsp;from&nbsp;&lt;<span class=number>0.13</span><span>.</span><span class=number>1</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&gt;&nbsp;link_demo:demonstrate_exit(hello).&nbsp;&nbsp;</span>
    <li class=alt><span>Demo&nbsp;process&nbsp;received&nbsp;exit&nbsp;signal&nbsp;hello&nbsp;from&nbsp;&lt;<span class=number>0.14</span><span>.</span><span class=number>1</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>**&nbsp;exited:&nbsp;hello&nbsp;**&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>&gt;&nbsp;link_demo:demonstrate_exit(normal).&nbsp;&nbsp;</span>
    <li class=alt><span>Demo&nbsp;process&nbsp;received&nbsp;normal&nbsp;exit&nbsp;from&nbsp;&lt;<span class=number>0.13</span><span>.</span><span class=number>1</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>**&nbsp;exited:&nbsp;normal&nbsp;**&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>&gt;&nbsp;link_demo:demonstrate_error().&nbsp;&nbsp;</span>
    <li class=alt><span>!!!&nbsp;Error&nbsp;in&nbsp;process&nbsp;&lt;<span class=number>0.17</span><span>.</span><span class=number>1</span><span>&gt;&nbsp;in&nbsp;function&nbsp;&nbsp;</span></span>
    <li class=""><span>!!!&nbsp;link_demo:demonstrate_error()&nbsp;&nbsp;</span>
    <li class=alt><span>!!!&nbsp;reason&nbsp;badmatch&nbsp;&nbsp;</span>
    <li class=""><span>**&nbsp;exited:&nbsp;badmatch&nbsp;**&nbsp;&nbsp;</span>
    <li class=alt><span>Demo&nbsp;process&nbsp;received&nbsp;exit&nbsp;signal&nbsp;badmatch&nbsp;from&nbsp;&lt;<span class=number>0.17</span><span>.</span><span class=number>1</span><span>&gt;&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br><span style="FONT-WEIGHT: bold">六、未定义函数和未注册名字</span><br>1.当调用一个未定义的函数时，Mod:Func(Arg0,...,ArgN)，这个调用将被转为：<br>error_handler:undefined_function(Mod, Func, [Arg0,...,ArgN]) <br>其中的error_handler模块是系统自带的错误处理模块<br><br>2.当给一个未注册的进程名发送消息时，调用将被转为：<br>error_handler:unregistered_name(Name,Pid,Message) <br><br>3.如果不使用系统自带的error_handler，可以通过process_flag(error_handler, MyMod) 设置自己的错误处理模块。<br><br><span style="FONT-WEIGHT: bold">七、Catch Vs. Trapping Exits</span><br>这两者的区别在于应用场景不同，Trapping Exits应用于当接收到其他进程发送的EXIT信号时，而catch仅用于表达式的执行。<br><br>第8章介绍了如何利用错误处理机制去构造一个健壮的系统，用了几个例子，我将8.2节的例子完整写了下，并添加客户端进程用于测试：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(allocator).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([start/<span class=number>1</span><span>,server/</span><span class=number>2</span><span>,allocate/</span><span class=number>0</span><span>,free/</span><span class=number>1</span><span>,start_client/</span><span class=number>0</span><span>,loop/</span><span class=number>0</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>start(Resources)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Pid&nbsp;=&nbsp;spawn(allocator,&nbsp;server,&nbsp;[Resources,[]]),&nbsp;&nbsp;</span>
    <li class=alt><span>register(resource_alloc,&nbsp;Pid).&nbsp;&nbsp;</span>
    <li class=""><span>%函数接口&nbsp;&nbsp;</span>
    <li class=alt><span>allocate()&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;request(alloc).&nbsp;&nbsp;</span>
    <li class=alt><span>free(Resource)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;request({free,Resource}).&nbsp;&nbsp;</span>
    <li class=alt><span>request(Request)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;resource_alloc&nbsp;!&nbsp;{self(),Request},&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{resource_alloc,&nbsp;error}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(bad_allocation);&nbsp;%&nbsp;exit&nbsp;added&nbsp;here&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{resource_alloc,&nbsp;Reply}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reply&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;end.&nbsp;&nbsp;</span>
    <li class=alt><span>%&nbsp;The&nbsp;server.&nbsp;&nbsp;</span>
    <li class=""><span>server(Free,&nbsp;Allocated)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;process_flag(trap_exit,&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>),&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;{From,alloc}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allocate(Free,&nbsp;Allocated,&nbsp;From);&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;{From,{free,R}}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(Free,&nbsp;Allocated,&nbsp;From,&nbsp;R);&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;{'EXIT',&nbsp;From,&nbsp;_&nbsp;}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;check(Free,&nbsp;Allocated,&nbsp;From)&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;end.&nbsp;&nbsp;</span>
    <li class=""><span>allocate([R|Free],&nbsp;Allocated,&nbsp;From)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;link(From),&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"连接客户端进程~w~n"</font></span><span>,[From]),&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;From&nbsp;!&nbsp;{resource_alloc,{yes,R}},&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;server(Free,&nbsp;[{R,From}|Allocated]);&nbsp;&nbsp;</span>
    <li class=alt><span>allocate([],&nbsp;Allocated,&nbsp;From)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;From&nbsp;!&nbsp;{resource_alloc,no},&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;server([],&nbsp;Allocated).&nbsp;&nbsp;</span>
    <li class=""><span>free(Free,&nbsp;Allocated,&nbsp;From,&nbsp;R)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>case</font></strong></span><span>&nbsp;lists:member({R,From},&nbsp;Allocated)&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;From&nbsp;!&nbsp;{resource_alloc,ok},&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Allocated1&nbsp;=&nbsp;lists:delete({R,&nbsp;From},&nbsp;Allocated),&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>case</font></strong></span><span>&nbsp;lists:keysearch(From,</span><span class=number>2</span><span>,Allocated1)&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>false</font></strong></span><span>-&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlink(From),&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"从进程~w断开~n"</font></span><span>,[From]);&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end,&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server([R|Free],Allocated1);&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>false</font></strong></span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;From&nbsp;!&nbsp;{resource_alloc,error},&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server(Free,&nbsp;Allocated)&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;end.&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>check(Free,&nbsp;Allocated,&nbsp;From)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>case</font></strong></span><span>&nbsp;lists:keysearch(From,&nbsp;</span><span class=number>2</span><span>,&nbsp;Allocated)&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>false</font></strong></span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server(Free,&nbsp;Allocated);&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{value,&nbsp;{R,&nbsp;From}}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;check([R|Free],&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lists:delete({R,&nbsp;From},&nbsp;Allocated),&nbsp;From)&nbsp;&nbsp;</span>
    <li class=alt><span>end.&nbsp;&nbsp;</span>
    <li class=""><span>start_client()-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;Pid2=spawn(allocator,loop,[]),&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;register(client,&nbsp;Pid2).&nbsp;&nbsp;</span>
    <li class=alt><span>loop()-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allocate-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allocate(),&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop();&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{free,Resource}-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(Resource),&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop();&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop()&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>回家了，有空再详细说明下这个例子吧。执行：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=number>1</span><span>&gt;&nbsp;c(allocator).&nbsp;&nbsp;</span></span>
    <li class=""><span>{ok,allocator}&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>2</span><span>&gt;&nbsp;allocator:start([</span><span class=number>1</span><span>,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>,</span><span class=number>5</span><span>,</span><span class=number>6</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>3</span><span>&gt;&nbsp;allocator:start_client().&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>4</span><span>&gt;&nbsp;client!allocate&nbsp;&nbsp;</span></span>
    <li class=""><span>.&nbsp;&nbsp;</span>
    <li class=alt><span>allocate连接客户端进程&lt;<span class=number>0.37</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>5</span><span>&gt;&nbsp;client!allocate.&nbsp;&nbsp;</span></span>
    <li class=""><span>allocate连接客户端进程&lt;<span class=number>0.37</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span><span class=number>6</span><span>&gt;&nbsp;client!allocate.&nbsp;&nbsp;</span></span>
    <li class=alt><span>allocate连接客户端进程&lt;<span class=number>0.37</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>7</span><span>&gt;&nbsp;allocator:allocate().&nbsp;&nbsp;</span></span>
    <li class=""><span>连接客户端进程&lt;<span class=number>0.28</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>{yes,<span class=number>4</span><span>}&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>8</span><span>&gt;&nbsp;client!{free,</span><span class=number>1</span><span>}.&nbsp;&nbsp;</span></span>
    <li class=alt><span>{free,<span class=number>1</span><span>}&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>9</span><span>&gt;&nbsp;client!{free,</span><span class=number>2</span><span>}.&nbsp;&nbsp;</span></span>
    <li class=alt><span>{free,<span class=number>2</span><span>}&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>10</span><span>&gt;&nbsp;client!allocate.&nbsp;&nbsp;</span></span>
    <li class=alt><span>allocate连接客户端进程&lt;<span class=number>0.37</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>11</span><span>&gt;&nbsp;client!allocate.&nbsp;&nbsp;</span></span>
    <li class=""><span>allocate连接客户端进程&lt;<span class=number>0.37</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span><span class=number>12</span><span>&gt;&nbsp;client!stop.&nbsp;&nbsp;</span></span>
    <li class=alt><span>stop&nbsp;&nbsp;</span>
    <li class=""><span><span class=number>13</span><span>&gt;&nbsp;allocator:allocate().&nbsp;&nbsp;</span></span>
    <li class=alt><span>连接客户端进程&lt;<span class=number>0.28</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>{yes,<span class=number>3</span><span>}&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>14</span><span>&gt;&nbsp;allocator:allocate().&nbsp;&nbsp;</span></span>
    <li class=""><span>连接客户端进程&lt;<span class=number>0.28</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span>{yes,<span class=number>2</span><span>}&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>15</span><span>&gt;&nbsp;allocator:allocate().&nbsp;&nbsp;</span></span>
    <li class=alt><span>连接客户端进程&lt;<span class=number>0.28</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>{yes,<span class=number>1</span><span>}&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>16</span><span>&gt;&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>
<img src ="http://www.cppblog.com/keigoliye/aggbug/95887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-11 10:13 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/11/95887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门（二）—并发编程</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/11/95885.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 11 Sep 2009 02:12:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/11/95885.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/95885.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/11/95885.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/95885.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/95885.html</trackback:ping><description><![CDATA[<div class=blog_content>&nbsp;&nbsp;&nbsp; Erlang中的process——进程是轻量级的，并且进程间无共享。查了很多资料，似乎没人说清楚轻量级进程算是什么概念，继续查找中。。。闲话不 提，进入并发编程的世界。本文算是学习笔记，也可以说是《Concurrent Programming in ERLANG》第五张的简略翻译。 <br><span style="FONT-WEIGHT: bold">1.进程的创建</span><br>&nbsp;&nbsp;&nbsp; 进程是一种自包含的、分隔的计算单元，并与其他进程并发运行在系统中，在进程间并没有一个继承体系，当然，应用开发者可以设计这样一个继承体系。<br>&nbsp;&nbsp;&nbsp; 进程的创建使用如下语法：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>Pid&nbsp;=&nbsp;spawn(Module,&nbsp;FunctionName,&nbsp;ArgumentList)&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>spawn接受三个参数：模块名，函数名以及参数列表，并返回一个代表创建的进程的标识符（Pid）。<br>如果在一个已知进程Pid1中执行：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>Pid2&nbsp;=&nbsp;spawn(Mod,&nbsp;Func,&nbsp;Args)&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>那么，Pid2仅仅能被Pid1可见，Erlang系统的安全性就构建在限制进程扩展的基础上。<br><br><span style="FONT-WEIGHT: bold">2.进程间通信</span><br>&nbsp;&nbsp;&nbsp; Erlang进程间的通信只能通过发送消息来实现，消息的发送使用!符号：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>Pid&nbsp;!&nbsp;Message&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>&nbsp;&nbsp;&nbsp; 其中Pid是接受消息的进程标记符，Message就是消息。接受方和消息可以是任何的有效的Erlang结构，只要他们的结果返回的是进程标记符和消息。<br>&nbsp;&nbsp;&nbsp; 消息的接受是使用receive关键字，语法如下：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>receive&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Message1&nbsp;[when&nbsp;Guard1]&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Actions1&nbsp;;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Message2&nbsp;[when&nbsp;Guard2]&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Actions2&nbsp;;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>end&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>&nbsp;&nbsp;&nbsp; 每一个Erlang进程都有一个&#8220;邮箱&#8221;，所有发送到进程的消息都按照到达的顺序存储在&#8220;邮箱&#8221;里，上面所示的消息Message1,Message2， 当它们与&#8220;邮箱&#8221;里的消息匹配，并且约束（Guard）通过，那么相应的ActionN将执行，并且receive返回的是ActionN的最后一条执行 语句的结果。Erlang对&#8220;邮箱&#8221;里的消息匹配是有选择性的，只有匹配的消息将被触发相应的Action，而没有匹配的消息将仍然保留在&#8220;邮箱&#8221;里。这 一机制保证了没有消息会阻塞其他消息的到达。<br>&nbsp;&nbsp;&nbsp; 消息到达的顺序并不决定消息的优先级，进程将轮流检查&#8220;邮箱&#8221;里的消息进行尝试匹配。消息的优先级别下文再讲。<br><br>&nbsp;&nbsp;&nbsp; 如何接受特定进程的消息呢？答案很简单，将发送方(sender)也附送在消息当中，接收方通过模式匹配决定是否接受，比如：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>Pid&nbsp;!&nbsp;{self(),abc}&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>给进程Pid发送消息{self(),abc}，利用self过程得到发送方作为消息发送。然后接收方：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>receive&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;{Pid1,Msg}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>end&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>通过模式匹配决定只有Pid1进程发送的消息才接受。<br><br><span style="FONT-WEIGHT: bold">3.一些例子</span><br>&nbsp;&nbsp;&nbsp; 仅说明下书中计数的进程例子,我添加了简单注释：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(counter).&nbsp;&nbsp;</span></span>
    <li class=""><span>-compile(export_all).&nbsp;&nbsp;</span>
    <li class=alt><span>%&nbsp;start()，返回一个新进程，进程执行函数loop&nbsp;&nbsp;</span>
    <li class=""><span>start()-&gt;spawn(counter,&nbsp;loop,[<span class=number>0</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>%&nbsp;调用此操作递增计数&nbsp;&nbsp;</span>
    <li class=""><span>increment(Counter)-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;Counter!increament.&nbsp;&nbsp;</span>
    <li class=""><span>%&nbsp;返回当前计数值&nbsp;&nbsp;</span>
    <li class=alt><span>value(Counter)-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Counter!{self(),value},&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Counter,Value}-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%返回给调用方&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;%停止计数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;stop(Counter)-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Counter!{self(),stop}.&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;loop(Val)-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%接受不同的消息，决定返回结果&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;increament-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop(Val+<span class=number>1</span><span>);&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{From,value}-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;From!{self(),Val},&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop(Val);&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>;&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%不是以上<span class=number>3</span><span>种消息，就继续等待&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Other-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop(Val)&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>调用方式：<br><br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=number>1</span><span>&gt;&nbsp;Counter1=counter:start().&nbsp;&nbsp;</span></span>
    <li class=""><span>&lt;<span class=number>0.30</span><span>.</span><span class=number>0</span><span>&gt;&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>2</span><span>&gt;&nbsp;counter:value(Counter1).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>0</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>3</span><span>&gt;&nbsp;counter:increment(Counter1).&nbsp;&nbsp;</span></span>
    <li class=""><span>increament&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>4</span><span>&gt;&nbsp;counter:value(Counter1).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>1</span><span>&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<br>基于进程的消息传递机制可以很容易地实现有限状态机（FSM），状态使用函数表示，而事件就是消息。具体不再展开<br><br><span style="FONT-WEIGHT: bold">4.超时设置</span><br>&nbsp;&nbsp;&nbsp; Erlang中的receive语法可以添加一个额外选项：timeout，类似：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>receive&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Message1&nbsp;[when&nbsp;Guard1]&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Actions1&nbsp;;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Message2&nbsp;[when&nbsp;Guard2]&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Actions2&nbsp;;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;after&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeOutExpr&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionsT&nbsp;&nbsp;</span>
    <li class=""><span>end&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>after之后的TimeOutExpr表达式返回一个整数time（毫秒级别），时间的精确程度依赖于Erlang在操作系统或者硬件的实现。如果在time毫秒内，没有一个消息被选中，超时设置将生效，也就是ActionT将执行。time有两个特殊值：<br>1)<span style="FONT-WEIGHT: bold">infinity</span>(无穷大)，infinity是一个atom，指定了超时设置将永远不会被执行。<br>2) <span style="FONT-WEIGHT: bold">0</span>，超时如果设定为0意味着超时设置将立刻执行，但是系统将首先尝试当前&#8220;邮箱&#8221;里的消息。<br><br>&nbsp;&nbsp;&nbsp; 超时的常见几个应用，比如挂起当前进程多少毫秒：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>sleep(Time)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;after&nbsp;Time&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>end.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>&nbsp; &nbsp; 比如清空进程的&#8220;邮箱&#8221;,丢弃&#8220;邮箱&#8221;里的所有消息：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>flush_buffer()&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;AnyMessage&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flush_buffer()&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;after&nbsp;<span class=number>0</span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>end.&nbsp;&nbsp;</span> </li>
</ol>
</div>
&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 将当前进程永远挂起：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>suspend()&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;after&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;infinity&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;end.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br><span style="COLOR: rgb(0,0,0)">&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,0)"> &nbsp;&nbsp;&nbsp; 超时也可以应用于实现定时器，比如下面这个例子，创建一个进程，这个进程将在设定时间后向自己发送消息：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(timer).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([timeout/<span class=number>2</span><span>,cancel/</span><span class=number>1</span><span>,timer/</span><span class=number>3</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>timeout(Time,&nbsp;Alarm)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;spawn(timer,&nbsp;timer,&nbsp;[self(),Time,Alarm]).&nbsp;&nbsp;</span>
    <li class=alt><span>cancel(Timer)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Timer&nbsp;!&nbsp;{self(),cancel}.&nbsp;&nbsp;</span>
    <li class=alt><span>timer(Pid,&nbsp;Time,&nbsp;Alarm)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;receive&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;{Pid,cancel}&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=keyword><strong><font color=#7f0055>true</font></strong></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;after&nbsp;Time&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pid&nbsp;!&nbsp;Alarm&nbsp;&nbsp;</span>
    <li class=alt><span>end.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br>&nbsp;&nbsp;&nbsp; <br><span style="FONT-WEIGHT: bold">5、注册进程</span><br>&nbsp;&nbsp;&nbsp; 为了给进程发送消息，我们需要知道进程的Pid，但是在某些情况下：在一个很大系统里面有很多的全局servers，或者为了安全考虑需要隐藏进程 Pid。为了达到可以发送消息给一个不知道Pid的进程的目的，我们提供了注册进程的办法，给进程们注册名字，这些名字必须是atom。<br>&nbsp;&nbsp;&nbsp; 基本的调用形式：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>register(Name,&nbsp;Pid)&nbsp;&nbsp;</span></span>
    <li class=""><span>将Name与进程Pid联系起来&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>unregister(Name)&nbsp;&nbsp;</span>
    <li class=alt><span>取消Name与相应进程的对应关系。&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>whereis(Name)&nbsp;&nbsp;</span>
    <li class=""><span>返回Name所关联的进程的Pid，如果没有进程与之关联，就返回atom:undefined&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>registered()&nbsp;&nbsp;</span>
    <li class=alt><span>返回当前注册的进程的名字列表&nbsp;&nbsp;</span> </li>
</ol>
</div>
<br><span style="FONT-WEIGHT: bold">6.进程的优先级</span><br>设定进程的优先级可以使用BIFs:<br><span style="FONT-WEIGHT: bold">process_flag(priority, Pri)</span> <br><br>Pri可以是normal、low,默认都是normal<br>优先级高的进程将相对低的执行多一点。<br><br><span style="FONT-WEIGHT: bold">7.进程组（process group)</span><br>&nbsp;&nbsp;&nbsp; 所有的ERLANG进程都有一个Pid与一个他们共有的称为Group Leader相关联，当一个新的进程被创建的时候将被加入同一个进程组。最初的系统进程的Group Leader就是它自身，因此它也是所有被创建进程及子进程的Group Leader。这就意味着Erlang的进程被组织为一棵Tree，其中的根节点就是第一个被创建的进程。下面的BIFs被用于操纵进程组：<br><span style="FONT-WEIGHT: bold">group_leader()</span><br>返回执行进程的Group Leader的Pid<br><span style="FONT-WEIGHT: bold">group_leader(Leader, Pid)</span><br>设置进程Pid的Group Leader为进程的Leader <br><br><span style="FONT-WEIGHT: bold">8.</span>Erlang的进程模型很容易去构建Client-Server的模型，书中有一节专门讨论了这一点，着重强调了接口的设计以及抽象层次的隔离问题，不翻译了。</span> </div>
<img src ="http://www.cppblog.com/keigoliye/aggbug/95885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-11 10:12 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/11/95885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门（一）</title><link>http://www.cppblog.com/keigoliye/archive/2009/09/11/95884.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Fri, 11 Sep 2009 02:11:00 GMT</pubDate><guid>http://www.cppblog.com/keigoliye/archive/2009/09/11/95884.html</guid><wfw:comment>http://www.cppblog.com/keigoliye/comments/95884.html</wfw:comment><comments>http://www.cppblog.com/keigoliye/archive/2009/09/11/95884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keigoliye/comments/commentRss/95884.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keigoliye/services/trackbacks/95884.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp; 读erlang.org上面的Erlang Course四天教程<br><span style="FONT-WEIGHT: bold">1.</span>数字类型，需要注意两点<br>1）B#Val表示以B进制存储的数字Val，比如<br></p>
<div class=code_title>ruby 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-rb>
    <li class=alt><span><span>7&gt;&nbsp;2</span><span class=comment><font color=#008200>#101.</font></span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>5&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><span style="COLOR: rgb(128,0,0)"><span style="COLOR: rgb(128,0,0)"><span style="COLOR: rgb(0,0,0)"><span style="FONT-WEIGHT: bold">二</span>进制存储的101就是10进制的5了<br>2）$Char表示字符Char的ascii编码，比如$A表示65<br><br><span style="FONT-WEIGHT: bold"></span><span style="FONT-WEIGHT: bold">2.</span>比较难以翻译的概念——atom，可以理解成常量，它可以包含任何字符，以小写字母开头，如果不是以小写字母开头或者是字母之外的符号，需要用单引号包括起来，比如abc,'AB'<span style="COLOR: rgb(128,0,0)"><span style="FONT-WEIGHT: bold"><br><br><span style="FONT-WEIGHT: bold">3.</span>另一个概念——Tuple,有人翻译成元组，可以理解成定长数组，是Erlang的基础数据结构之一：<br></p>
<div class=code_title>ruby 代码</div>
<div class=dp-highlighter>
<ol class=dp-rb>
    <li class=alt><span><span><font color=#000000>8&gt;&nbsp;{1,2,3,4,5}.&nbsp;&nbsp;</font></span></span>
    <li class=""><span><font color=#000000>{1,2,3,4,5}&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>9&gt;&nbsp;{a,b,c,1,2}.&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>{a,b,c,1,2}&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>10&gt;&nbsp;size({1,2,3,a,b,c}).&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>6&nbsp;&nbsp;</font></span> </li>
</ol>
</div>
<p><br>内置函数size求长度，元组可以嵌套元组或者其他结构。下面所讲的列表也一样。<br><br><span style="FONT-WEIGHT: bold">4.</span>另外一个基础数据结构就是各个语言都有的list（列表），在[]内以,隔开，可以动态改变大小， <br></p>
<div class=code_title>python 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-py>
    <li class=alt><span><span><font color=#000000>[123,&nbsp;xyz]&nbsp;&nbsp;</font></span></span>
    <li class=""><span><font color=#000000>[123,&nbsp;</font><span class=keyword><font color=#7f0055>def</font></span><span><font color=#000000>,&nbsp;abc]&nbsp;&nbsp;</font></span></span>
    <li class=alt><span><font color=#000000>[{person,&nbsp;'Joe',&nbsp;'Armstrong'},&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;{person,&nbsp;'Robert',&nbsp;'Virding'},&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;{person,&nbsp;'Mike',&nbsp;'Williams'}&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>]&nbsp;&nbsp;</font></span> </li>
</ol>
</div>
<p><br>可以使用内置函数length求列表大小。以""包含的ascii字母代表一个列表，里面的元素就是这些字母的ascii值，比如"abc"表示列表[97,98,99]。<br><br><span style="FONT-WEIGHT: bold">5.</span>通过这两个数据结构可以组合成各种复杂结构，与Lisp的cons、list演化出各种结构一样的奇妙。<br><br><span style="FONT-WEIGHT: bold">6.</span>Erlang中变量有两个特点：<br>1）变量必须以大写字母开头<br>2）变量只能绑定一次，或者以一般的说法就是只能赋值一次，其实Erlang并没有赋值这样的概念,=号也是用于验证匹配。<br><br><span style="FONT-WEIGHT: bold">7.</span>模式匹配——Pattern Matching，Erlang的模式匹配非常强大，看了<strong>buaawhl</strong>的《<a href="http://www.javaeye.com/topic/83858"><u><font color=#000000>Erlang语法提要</font></u></a>》的介绍，模式匹配的功能不仅仅在课程中介绍的数据结构的拆解，在程序的分派也扮演重要角色，或者说Erlang的控制的流转是通过模式匹配来实现的。具体功能参见链接，给出书中拆解列表的例子：<br></p>
<div class=code_title>python 代码</div>
<div class=dp-highlighter>
<ol class=dp-py>
    <li class=alt><span><span><font color=#000000>[A,B|C]&nbsp;=&nbsp;[1,2,3,4,5,6,7]&nbsp;&nbsp;</font></span></span>
    <li class=""><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Succeeds&nbsp;-&nbsp;binds&nbsp;A&nbsp;=&nbsp;1,&nbsp;B&nbsp;=&nbsp;2,&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;=&nbsp;[3,4,5,6,7]&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>&nbsp;&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>&nbsp;[H|T]&nbsp;=&nbsp;[1,2,3,4]&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Succeeds&nbsp;-&nbsp;binds&nbsp;H&nbsp;=&nbsp;1,&nbsp;T&nbsp;=&nbsp;[2,3,4]&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>&nbsp;&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>&nbsp;[H|T]&nbsp;=&nbsp;[abc]&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Succeeds&nbsp;-&nbsp;binds&nbsp;H&nbsp;=&nbsp;abc,&nbsp;T&nbsp;=&nbsp;[]&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>&nbsp;&nbsp;&nbsp;</font></span>
    <li class=alt><span><font color=#000000>&nbsp;[H|T]&nbsp;=&nbsp;[]&nbsp;&nbsp;</font></span>
    <li class=""><span><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Fails&nbsp;&nbsp;</font></span> </li>
</ol>
</div>
<p><!----><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)"> <br>下面会给出更多模式匹配的例子，给出一个模块用来计算列表等<br><br><span style="FONT-WEIGHT: bold">8.</span>Erlang中函数的定义必须在一个模块内（Module），并且模块和函数的名称都必须是atom，函数的参数可以是任何的Erlang类型或者数据结构，函数要被调用需要从模块中导出，函数调用的形式类似：<br>moduleName:funcName(Arg1,Arg2,...).<br>写我们的第一个Erlang程序，人见人爱的Hello World：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(helloWorld).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([run/<span class=number>1</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>run(Name)-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Hello&nbsp;World&nbsp;~w~n"</font></span><span>,[Name]).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br>存为helloWorld.erl，在Erlang Shell中执行：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=number>2</span><span>&gt;&nbsp;c(helloWorld).&nbsp;&nbsp;</span></span>
    <li class=""><span>{ok,helloWorld}&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>3</span><span>&gt;&nbsp;helloWorld:run(dennis).&nbsp;&nbsp;</span></span>
    <li class=""><span>Hello&nbsp;World&nbsp;dennis&nbsp;&nbsp;</span>
    <li class=alt><span>ok&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br>打印出来了，现在解释下程序构造，<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>-module(helloWorld).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br>这一行声明了模块helloWorld，函数必须定义在模块内，并且模块名称必须与源文件名相同。<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-export([run/</span><span class=number>1</span><span>]).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br>而这一行声明导出的函数，run/1指的是有一个参数的run函数，因为Erlang允许定义同名的有不同参数的多个函数，通过指定/1来说明要导出的是哪个函数。<br>接下来就是函数定义了：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>run(Name)-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;io:format(<span class=string><font color=#0000ff>"Hello&nbsp;World&nbsp;~w~n"</font></span><span>,[Name]).&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br>大写开头的是变量Name，调用io模块的format方法输出，~w可以理解成占位符，将被实际Name取代，~n就是换行了。注意，函数定义完了要以句号.结束。然后执行c(helloWorld).编译源代码，执行：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>helloWorld:run(dennis);&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br><span style="FONT-WEIGHT: bold">9.</span>内置的常用函数：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>date()&nbsp;&nbsp;</span></span>
    <li class=""><span>time()&nbsp;&nbsp;</span>
    <li class=alt><span>length([<span class=number>1</span><span>,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>,</span><span class=number>5</span><span>])&nbsp;&nbsp;</span></span>
    <li class=""><span>size({a,b,c})&nbsp;&nbsp;</span>
    <li class=alt><span>atom_to_list(an_atom)&nbsp;&nbsp;</span>
    <li class=""><span>list_to_tuple([<span class=number>1</span><span>,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>])&nbsp;&nbsp;</span></span>
    <li class=alt><span>integer_to_list(<span class=number>2234</span><span>)&nbsp;&nbsp;</span></span>
    <li class=""><span>tuple_to_list({})&nbsp;&nbsp;</span>
    <li class=alt><span>hd([<span class=number>1</span><span>,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>])&nbsp;&nbsp;%输出</span><span class=number>1</span><span>，也就是列表的head&nbsp;&nbsp;</span></span>
    <li class=""><span>tl([<span class=number>1</span><span>,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>])&nbsp;&nbsp;%输出[</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>],也就是列表的tail&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br><span style="FONT-WEIGHT: bold">10.</span>常见Shell命令：<br>1）<span style="FONT-WEIGHT: bold">h().</span> 用来打印最近的20条历史命令<br>2）<span style="FONT-WEIGHT: bold">b().</span> 查看所有绑定的变量<br>3) <span style="FONT-WEIGHT: bold">f().</span> 取消（遗忘）所有绑定的变量。<br>4) <span style="FONT-WEIGHT: bold">f(Val).</span>&nbsp; 取消指定的绑定变量<br>5) <span style="FONT-WEIGHT: bold">e(n).</span>&nbsp;&nbsp; 执行第n条历史命令<br>6) <span style="FONT-WEIGHT: bold">e(-1).</span>&nbsp; 执行上一条shell命令<br><br><span style="FONT-WEIGHT: bold">11.</span>又一个不知道怎么翻译的概念——Guard。翻译成约束？呵呵。用于限制变量的类型和范围，比如：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>number(X)&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是数字&nbsp;&nbsp;</span></span>
    <li class=""><span>integer(X)&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是整数&nbsp;&nbsp;</span>
    <li class=alt><span><span class=keyword><font color=#7f0055>float</font></span><span>(X)&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是浮点数&nbsp;&nbsp;</span></span>
    <li class=""><span>atom(X)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是一个atom&nbsp;&nbsp;</span>
    <li class=alt><span>tuple(X)&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是一个元组&nbsp;&nbsp;</span>
    <li class=""><span>list(X)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是一个列表&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;</span>
    <li class=""><span>length(X)&nbsp;==&nbsp;<span class=number>3</span><span>&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是一个长度为</span><span class=number>3</span><span>的列表&nbsp;&nbsp;</span></span>
    <li class=alt><span>size(X)&nbsp;==&nbsp;<span class=number>2</span><span>&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;是一个长度为</span><span class=number>2</span><span>的元组&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>X&nbsp;&gt;&nbsp;Y&nbsp;+&nbsp;Z&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;&gt;Y+Z&nbsp;&nbsp;</span>
    <li class=""><span>X&nbsp;==&nbsp;Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;与Y相等&nbsp;&nbsp;</span>
    <li class=alt><span>X&nbsp;=:=&nbsp;Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;X&nbsp;全等于Y&nbsp;&nbsp;</span>
    <li class=""><span>(比如：&nbsp;<span class=number>1</span><span>&nbsp;==&nbsp;</span><span class=number>1.0</span><span>&nbsp;成功&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=number>1</span><span>&nbsp;=:=&nbsp;</span><span class=number>1.0</span><span>&nbsp;失败)&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br>为了方便比较，Erlang规定如下的比较顺序：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>number&nbsp;&lt;&nbsp;atom&nbsp;&lt;&nbsp;reference&nbsp;&lt;&nbsp;port&nbsp;&lt;&nbsp;pid&nbsp;&lt;&nbsp;tuple&nbsp;&lt;&nbsp;list&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br><br><span style="FONT-WEIGHT: bold">12.</span>忘了介绍apply函数，这个函数对于熟悉javascript的人来说很亲切，javascript实现mixin就得靠它，它的调用方式如下：<br></p>
<pre>apply(Mod, Func, Args),三个参数分别是模块、函数以及参数列表，比如调用我们的第一个Erlang程序：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<ol class=dp-j>
    <li class=alt><span><span>apply(helloWorld,run,[dennis]).&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br><span style="FONT-WEIGHT: bold">13.</span>if和case语句，if语句的结构如下：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=keyword><font color=#7f0055>if</font></span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Guard1&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sequence1&nbsp;;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Guard2&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sequence2&nbsp;;&nbsp;&nbsp;</span>
    <li class=""><span>...&nbsp;&nbsp;</span>
    <li class=alt><span>end&nbsp;&nbsp;</span></li>
</ol>
</div>
<br>而case语句的结构如下：<br>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=keyword><font color=#7f0055>case</font></span><span>&nbsp;Expr&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Pattern1&nbsp;[when&nbsp;Guard1]&nbsp;-&gt;&nbsp;Seq1;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;Pattern2&nbsp;[when&nbsp;Guard2]&nbsp;-&gt;&nbsp;Seq2;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;PatternN&nbsp;[when&nbsp;GuardN]&nbsp;-&gt;&nbsp;SeqN&nbsp;&nbsp;</span>
    <li class=""><span>end&nbsp;&nbsp;</span></li>
</ol>
</div>
</pre>
<p>if和case语句都有一个问题，就是当没有模式匹配或者Grard都是false的时候会导致error，这个问题case可以增加一个类似java中default的：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=keyword><font color=#7f0055>case</font></span><span>&nbsp;Fn&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;_&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class=keyword><font color=#7f0055>true</font></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>end&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br>通过_指代任意的Expr，返回true,而if可以这样：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=keyword><font color=#7f0055>if</font></span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;<span class=keyword><font color=#7f0055>true</font></span><span>&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class=keyword><font color=#7f0055>true</font></span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>end&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br>一样的道理。case语句另一个需要注意的问题就是变量范围，每个case分支中定义的变量都将默认导出case语句，也就是在case语句结束后可以被引用，因此一个规则就是每个case分支定义的变量应该一致，不然算是非法的，编译器会给出警告，比如：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>f(X)&nbsp;-&gt;&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><font color=#7f0055>case</font></span><span>&nbsp;g(X)&nbsp;of&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=keyword><font color=#7f0055>true</font></span><span>&nbsp;-&gt;&nbsp;A&nbsp;=&nbsp;h(X),&nbsp;B&nbsp;=&nbsp;A&nbsp;+&nbsp;</span><span class=number>7</span><span>;&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><font color=#7f0055>false</font></span><span>&nbsp;-&gt;&nbsp;B&nbsp;=&nbsp;</span><span class=number>6</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span>end,&nbsp;&nbsp;</span>
    <li class=""><span>h(A).&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br>如果执行true分支，变量A和变量B都被定义，而如果执行的false分支，只有变量B被引用，可在case语句执行后，h(A)调用了变量A，这是不安全的，因为变量A完全可能没有被定义，编译器将给出警告<br><span style="FONT-WEIGHT: bold">variable 'A' unsafe in 'case' (line 10)</span><br><br><br><br><span style="FONT-WEIGHT: bold">14.</span>给出一些稍微复杂的模型匹配例子，比如用于计算数字列表的和、平均值、长度、查找某元素是否在列表中，我们把这个模块定义为list:<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(list).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([average/<span class=number>1</span><span>,sum/</span><span class=number>1</span><span>,len/</span><span class=number>1</span><span>,</span><span class=keyword><font color=#7f0055>double</font></span><span>/</span><span class=number>1</span><span>,member/</span><span class=number>2</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>average(X)-&gt;sum(X)/len(X).&nbsp;&nbsp;</span>
    <li class=""><span>sum([H|T])&nbsp;when&nbsp;number(H)-&gt;H+sum(T);&nbsp;&nbsp;</span>
    <li class=alt><span>sum([])-&gt;<span class=number>0</span><span>.&nbsp;&nbsp;</span></span>
    <li class=""><span>len([_|T])-&gt;<span class=number>1</span><span>+len(T);&nbsp;&nbsp;</span></span>
    <li class=alt><span>len([])-&gt;<span class=number>0</span><span>.&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=keyword><font color=#7f0055>double</font></span><span>([H|T])&nbsp;-&gt;&nbsp;[</span><span class=number>2</span><span>*H|</span><span class=keyword><font color=#7f0055>double</font></span><span>(T)];&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=keyword><font color=#7f0055>double</font></span><span>([])&nbsp;-&gt;&nbsp;[].&nbsp;&nbsp;</span></span>
    <li class=""><span>member(H,&nbsp;[H|_])&nbsp;-&gt;&nbsp;<span class=keyword><font color=#7f0055>true</font></span><span>;&nbsp;&nbsp;</span></span>
    <li class=alt><span>member(H,&nbsp;[_|T])&nbsp;-&gt;&nbsp;member(H,&nbsp;T);&nbsp;&nbsp;</span>
    <li class=""><span>member(_,&nbsp;[])&nbsp;-&gt;&nbsp;<span class=keyword><font color=#7f0055>false</font></span><span>.&nbsp;&nbsp;</span></span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br>细细体会，利用递归来实现，比较有趣。_用于指代任意的变量，当我们只关注此处有变量，但并不关心变量的值的时候使用。用分号;来说明是同一个函数定义，只是不同的定义分支，通过模式匹配来决定调用哪个函数定义分支。<br>另一个例子，计算各种图形的面积，也是课程中给出的例子：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span>-module(mathStuff).&nbsp;&nbsp;</span></span>
    <li class=""><span>-export([factorial/<span class=number>1</span><span>,area/</span><span class=number>1</span><span>]).&nbsp;&nbsp;</span></span>
    <li class=alt><span>factorial(<span class=number>0</span><span>)-&gt;</span><span class=number>1</span><span>;&nbsp;&nbsp;</span></span>
    <li class=""><span>factorial(N)&nbsp;when&nbsp;N&gt;<span class=number>0</span><span>-&gt;N*factorial(N-</span><span class=number>1</span><span>).&nbsp;&nbsp;</span></span>
    <li class=alt><span>%计算正方形面积，参数元组的第一个匹配square&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=""><span>area({square,&nbsp;Side})&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;&nbsp;Side&nbsp;*&nbsp;Side;&nbsp;&nbsp;</span>
    <li class=""><span>%计算圆的面积，匹配circle&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>area({circle,&nbsp;Radius})&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;%&nbsp;almost&nbsp;:-)&nbsp;&nbsp;</span>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;<span class=number>3</span><span>&nbsp;*&nbsp;Radius&nbsp;*&nbsp;Radius;&nbsp;&nbsp;</span></span>
    <li class=""><span>%计算三角形的面积，利用海伦公式，匹配triangle&nbsp;&nbsp;&nbsp;</span>
    <li class=alt><span>area({triangle,&nbsp;A,&nbsp;B,&nbsp;C})&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;S&nbsp;=&nbsp;(A&nbsp;+&nbsp;B&nbsp;+&nbsp;C)/<span class=number>2</span><span>,&nbsp;&nbsp;</span></span>
    <li class=alt><span>math:sqrt(S*(S-A)*(S-B)*(S-C));&nbsp;&nbsp;</span>
    <li class=""><span>%其他&nbsp;&nbsp;</span>
    <li class=alt><span>area(Other)&nbsp;-&gt;&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;{invalid_object,&nbsp;Other}.&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br>执行一下看看：<br></p>
<div class=code_title>java 代码</div>
<div class=dp-highlighter>
<div class=bar>&nbsp;</div>
<ol class=dp-j>
    <li class=alt><span><span class=number>1</span><span>&gt;&nbsp;c(mathStuff).&nbsp;&nbsp;</span></span>
    <li class=""><span>{ok,mathStuff}&nbsp;&nbsp;</span>
    <li class=alt><span><span class=number>2</span><span>&gt;&nbsp;mathStuff:area({square,</span><span class=number>2</span><span>}).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>4</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>3</span><span>&gt;&nbsp;mathStuff:area({circle,</span><span class=number>2</span><span>}).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>12</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>4</span><span>&gt;&nbsp;mathStuff:area({triangle,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>}).&nbsp;&nbsp;</span></span>
    <li class=""><span><span class=number>2.90474</span><span>&nbsp;&nbsp;</span></span>
    <li class=alt><span><span class=number>5</span><span>&gt;&nbsp;mathStuff:area({other,</span><span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>}).&nbsp;&nbsp;</span></span>
    <li class=""><span>{invalid_object,{other,<span class=number>2</span><span>,</span><span class=number>3</span><span>,</span><span class=number>4</span><span>}}&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p><br>Erlang使用%开始单行注释。<br></span></span></span></span></span></span></p>
<img src ="http://www.cppblog.com/keigoliye/aggbug/95884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keigoliye/" target="_blank">暗夜教父</a> 2009-09-11 10:11 <a href="http://www.cppblog.com/keigoliye/archive/2009/09/11/95884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>