﻿<?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>BlogJava-庄周梦蝶-随笔分类-unix网络编程</title><link>http://www.blogjava.net/killme2008/category/37396.html</link><description>生活、程序、未来</description><language>zh-cn</language><lastBuildDate>Thu, 17 Nov 2011 13:44:56 GMT</lastBuildDate><pubDate>Thu, 17 Nov 2011 13:44:56 GMT</pubDate><ttl>60</ttl><item><title>演示TCP慢启动和滑动窗口机制的动画</title><link>http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 15 Nov 2011 23:34:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/363913.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/363913.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/363913.html</trackback:ping><description><![CDATA[今天看到的一个演示TCP慢启动和滑动窗口机制的动画，很形象<br />
<a href="http://www.osischool.com" target="_blank">osischool.com</a><br />
<embed type="application/x-shockwave-flash" width="620" height="400" src="http://www.blogjava.net/Files/killme2008/tcp_slow_start.zip"></embed><img src ="http://www.blogjava.net/killme2008/aggbug/363913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2011-11-16 07:34 <a href="http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络编程中Nagle算法和Delayed ACK的测试</title><link>http://www.blogjava.net/killme2008/archive/2011/06/30/353441.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 30 Jun 2011 08:01:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2011/06/30/353441.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/353441.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2011/06/30/353441.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/353441.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/353441.html</trackback:ping><description><![CDATA[<br />&nbsp;&nbsp;&nbsp; <a href="http://en.wikipedia.org/wiki/Nagle%27s_algorithm">Nagle算法</a>的立意是良好的，避免网络中充塞小封包，提高网络的利用率。但是当Nagle算法遇到<a href="http://en.wikipedia.org/wiki/TCP_delayed_acknowledgment">delayed ACK</a>悲剧就发生了。Delayed ACK的本意也是为了提高TCP性能，跟应答数据捎带上ACK，同时避免<a href="http://hi.baidu.com/iruler/blog/item/ac2661f4c4aabe63ddc474ae.html">糊涂窗口综合症</a>，也可以一个ack确认多个段来节省开销。<br />&nbsp;&nbsp;&nbsp; 悲剧发生在这种情况，假设一端发送数据并等待另一端应答，协议上分为头部和数据，发送的时候不幸地选择了write-write，然后再read，也就是先发送头部，再发送数据，最后等待应答。发送端的伪代码是这样<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">write(head);<br />write(body);<br />read(response);</span></div><br />接收端的处理代码类似这样：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">read(request);<br />process(request);<br />write(response);</span></div><br />&nbsp;&nbsp; 这里假设head和body都比较小，当默认启用nagle算法，并且是第一次发送的时候，根据nagle算法，第一个段head可以立即发送，因为没有等待确认的段；接收端收到head，但是包不完整，继续等待body达到并延迟ACK；发送端继续写入body，这时候nagle算法起作用了，因为head还没有被ACK，所以body要延迟发送。这就造成了发送端和接收端都在等待对方发送数据的现象，发送端等待接收端ACK head以便继续发送body，而接收端在等待发送方发送body并延迟ACK，悲剧的无以言语。这种时候只有等待一端超时并发送数据才能继续往下走。<br /><br />&nbsp;&nbsp; 正因为nagle算法和delayed ack的影响，再加上这种write-write-read的编程方式造成了很多网贴在讨论为什么自己写的网络程序性能那么差。然后很多人会在帖子里建议禁用Nagle算法吧，设置TCP_NODELAY为true即可禁用nagle算法。但是这真的是解决问题的唯一办法和最好办法吗？<br /><br />&nbsp;&nbsp; 其实问题不是出在nagle算法身上的，问题是出在write-write-read这种应用编程上。禁用nagle算法可以暂时解决问题，但是禁用nagle算法也带来很大坏处，网络中充塞着小封包，网络的利用率上不去，在极端情况下，大量小封包导致网络拥塞甚至崩溃。因此，能不禁止还是不禁止的好，后面我们会说下什么情况下才需要禁用nagle算法。对大多数应用来说，一般都是连续的请求&#8212;&#8212;应答模型，有请求同时有应答，那么请求包的ACK其实可以延迟到跟响应一起发送，在这种情况下，其实你只要避免write-write-read形式的调用就可以避免延迟现象，利用writev做聚集写或者将head和body一起写，然后再read，变成write-read-write-read的形式来调用，就无需禁用nagle算法也可以做到不延迟。<br /><br />&nbsp;&nbsp; writev是系统调用，在Java里是用到<a href="http://download.oracle.com/javase/1.5.0/docs/api/java/nio/channels/GatheringByteChannel.html">GatheringByteChannel</a>.write(ByteBuffer[] srcs, int offset, int length)方法来做聚集写。这里可能还有一点值的提下，很多同学看java nio框架几乎都不用这个writev调用，这是有原因的。主要是因为Java的write本身对ByteBuffer有做临时缓存，而writev没有做缓存，导致测试来看write反而比writev更高效，因此通常会更推荐用户将head和body放到同一个Buffer里来避免调用writev。<br /><br />&nbsp;&nbsp; 下面我们将做个实际的代码测试来结束讨论。这个例子很简单，客户端发送一行数据到服务器，服务器简单地将这行数据返回。客户端发送的时候可以选择分两次发，还是一次发送。分两次发就是write-write-read，一次发就是write-read-write-read，可以看看两种形式下延迟的差异。<strong>注意，在windows上测试下面的代码，客户端和服务器必须分在两台机器上，似乎winsock对loopback连接的处理不一样。</strong><br /><br />&nbsp;&nbsp;&nbsp; 服务器源码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;net.fnil.nagle;<br /><br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.BufferedReader;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.InputStream;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.InputStreamReader;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.OutputStream;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.net.InetSocketAddress;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.net.ServerSocket;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.net.Socket;<br /><br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Server&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000FF; ">throws</span><span style="color: #000000; ">&nbsp;Exception&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerSocket&nbsp;serverSocket&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ServerSocket();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serverSocket.bind(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;InetSocketAddress(</span><span style="color: #000000; ">8000</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Server&nbsp;startup&nbsp;at&nbsp;8000</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(;;)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;socket&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;serverSocket.accept();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;socket.getInputStream();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;socket.getOutputStream();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">try</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader&nbsp;reader&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;BufferedReader(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;InputStreamReader(in));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;line&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;reader.readLine();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write((line&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">\r\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">).getBytes());<br />&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(Exception&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br />&nbsp;&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;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span></div><br />服务端绑定到本地8000端口，并监听连接，连上来的时候就阻塞读取一行数据，并将数据返回给客户端。<br /><br />客户端代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;net.fnil.nagle;<br /><br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.BufferedReader;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.InputStream;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.InputStreamReader;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.OutputStream;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.net.InetSocketAddress;<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.net.Socket;<br /><br /><br /></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;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000FF; ">throws</span><span style="color: #000000; ">&nbsp;Exception&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;是否分开写head和body</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;writeSplit&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;host&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">localhost</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(args.length&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;args[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(args.length&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeSplit&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Boolean.valueOf(args[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">WriteSplit:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;writeSplit);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket&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();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.connect(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;InetSocketAddress(host,&nbsp;</span><span style="color: #000000; ">8000</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;socket.getInputStream();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;socket.getOutputStream();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader&nbsp;reader&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;BufferedReader(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;InputStreamReader(in));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;head&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">hello&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;body&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">world\r\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;label&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;System.currentTimeMillis();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(writeSplit)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(head.getBytes());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(body.getBytes());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write((head&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;body).getBytes());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;line&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;reader.readLine();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">RTT:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(System.currentTimeMillis()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;label)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;,receive:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;line);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}<br /></span></div><br /><br />&nbsp;&nbsp; 客户端通过一个writeSplit变量来控制是否分开写head和body，如果为true，则先写head再写body，否则将head加上body一次写入。客户端的逻辑也很简单，连上服务器，发送一行，等待应答并打印RTT，循环10次最后关闭连接。<br /><br />&nbsp;&nbsp; 首先，我们将writeSplit设置为true，也就是分两次写入一行，在我本机测试的结果，我的机器是ubuntu 11.10：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">WriteSplit:</span><span style="color: #0000FF; ">true</span><span style="color: #000000; "><br />RTT:</span><span style="color: #000000; ">8</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">39</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">40</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br /></span></div><br />&nbsp;&nbsp;&nbsp; 可以看到，每次请求到应答的时间间隔都在40ms，除了第一次。linux的delayed ack是40ms，而不是原来以为的200ms。第一次立即ACK，似乎跟linux的quickack mode有关，这里我不是特别清楚，有比较清楚的同学请指教。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; 接下来，我们还是将writeSplit设置为true，但是客户端禁用nagle算法，也就是客户端代码在connect之前加上一行：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket&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();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.setTcpNoDelay(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.connect(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;InetSocketAddress(host,&nbsp;</span><span style="color: #000000; ">8000</span><span style="color: #000000; ">));</span></div><br />&nbsp;&nbsp;&nbsp; 再跑下测试：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">WriteSplit:</span><span style="color: #0000FF; ">true</span><span style="color: #000000; "><br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br /></span></div><br />&nbsp;&nbsp; 这时候就正常多了，大部分RTT时间都在1毫秒以下。果然禁用Nagle算法可以解决延迟问题。<br />&nbsp;&nbsp; 如果我们不禁用nagle算法，而将writeSplit设置为false，也就是将head和body一次写入，再次运行测试（记的将setTcpNoDelay这行删除）：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">WriteSplit:</span><span style="color: #0000FF; ">false</span><span style="color: #000000; "><br />RTT:</span><span style="color: #000000; ">7</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000;">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br />RTT:</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;,receive:hello&nbsp;world<br /></span></div><br />&nbsp;&nbsp; 结果跟禁用nagle算法的效果类似。既然这样，我们还有什么理由一定要禁用nagle算法呢？通过我在<a href="http://code.google.com/p/xmemcached/downloads/list">xmemcached</a>的压测中的测试，启用nagle算法在小数据的存取上甚至有一定的效率优势，memcached协议本身就是个连续的请求应答的模型。上面的测试如果在windows上跑，会发现RTT最大会在200ms以上，可见winsock的delayed ack超时是200ms。<br /><br />&nbsp;&nbsp; 最后一个问题，什么情况下才应该禁用nagle算法？当你的应用不是这种连续的请求&#8212;&#8212;应答模型，而是需要实时地单向发送很多小数据的时候或者请求是有间隔的，则应该禁用nagle算法来提高响应性。一个最明显是例子是telnet应用，你总是希望敲入一行数据后能立即发送给服务器，然后马上看到应答，而不是说我要连续敲入很多命令或者等待200ms才能看到应答。<br /><br />&nbsp;&nbsp; 上面是我对nagle算法和delayed ack的理解和测试，有错误的地方请不吝赐教。<br /><br />&nbsp;&nbsp; 转载请注明出处：<a id="Editor_Edit_hlEntryLink" title="view: Nagle算法和Delayed ACK的一个测试" href="../archive/2011/06/30/353441.html" target="_blank">http://www.blogjava.net/killme2008/archive/2011/06/30/353441.html</a><br />&nbsp;&nbsp; <br />&nbsp;&nbsp;<img src ="http://www.blogjava.net/killme2008/aggbug/353441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2011-06-30 16:01 <a href="http://www.blogjava.net/killme2008/archive/2011/06/30/353441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java NIO编程的技巧和陷阱</title><link>http://www.blogjava.net/killme2008/archive/2011/06/30/353422.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 30 Jun 2011 03:07:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2011/06/30/353422.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/353422.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2011/06/30/353422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/353422.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/353422.html</trackback:ping><description><![CDATA[<br />
去年做的分享，一直上传slideshare失败，今天又试了下，成功了。这个主题主要介绍Java NIO编程的技巧和陷阱，解读了一些NIO框架的源码，以及编写高性能NIO网络框架所需要注意的技巧和缺陷。关注这方面的朋友可以看一下。去年写了篇blog提供了pdf版本的下载，看<a href="http://www.blogjava.net/killme2008/archive/2010/11/22/338420.html">这里</a>。<br />
<br />
<div style="width:500px" id="__ss_8464155"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/killme2008/nio-trick-and-trap-8464155" title="Nio trick and trap" target="_blank">Nio trick and trap</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/8464155" marginwidth="0" marginheight="0" frameborder="0" height="450" scrolling="no" width="500"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/killme2008" target="_blank">dennis zhuang</a> </div>
</div><img src ="http://www.blogjava.net/killme2008/aggbug/353422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2011-06-30 11:07 <a href="http://www.blogjava.net/killme2008/archive/2011/06/30/353422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unix domain socket和memcached</title><link>http://www.blogjava.net/killme2008/archive/2009/10/15/298301.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 14 Oct 2009 22:12:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/10/15/298301.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/298301.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/10/15/298301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/298301.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/298301.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; unix域协议并不是一个实际的协议族，而是在单个主机上执行客户／服务器通信的一种方法，是IPC的方法之一，特定于*nix平台。使用unix domain socket有三个好处：<br />
1）在同一主机上，unix domain socket比一般的tcp socket快上一倍，性能因素这是一个主要原因。<br />
2）unix domain socket可以在同一主机的不同进程之间传递文件描述符<br />
3）较新的unix domain socket实现把客户的ID和组ID提供给服务器，可以让服务器作安全检查。<br />
<br />
&nbsp;&nbsp; memcached的FAQ中也提到为了安全验证，可以考虑让memcached监听unix domain socket。Memcached支持这一点，可以通过-s选项指定unix domain socket的路径名，注意，为了可移植性，尽量使用绝对路径，因为Posix标准声称给unix domain socket绑定相对路径将导致不可预计的后果，我在linux的测试是可以使用相对路径。假设我将memcached绑定到/home/dennis/memcached，可以这样启动memcached:<br />
<strong><br />
memcached -s /home/dennis/memcached</strong><br />
<br />
端口呢？没有端口了，/home/dennis/memcached这个文件你可以理解成FIFO的管道，unix domain socket的server/client通过这个管道通讯。<br />
<br />
&nbsp;&nbsp; libmemcached支持通过unix domain socket来访问memcached，基于libmemcached实现的client应该都可以使用这一功能。目前来看，java平台由于不支持平台相关的unix domain socket，因此无法享受memcached的这一特性。<br />
<br />
&nbsp;&nbsp; 不过有一个开源项目通过jni支持实现了unix domain socket，这个项目称为<a title="juds" href="http://code.google.com/p/juds/">juds</a>。核心类就三个，使用非常简单。下载文件后，解压缩，make &amp; make install即可。注意，Makefile中写死了JAVA_HOME，手工修改即可。看一个例子，经典的Time server:<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: #0000ff;">package</span><span style="color: #000000;">&nbsp;com.google.code.juds.test;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.IOException;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;com.google.code.juds.</span><span style="color: #000000;">*</span><span style="color: #000000;">;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.</span><span style="color: #000000;">*</span><span style="color: #000000;">;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.text.DateFormat;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.text.SimpleDateFormat;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Date;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;TimeServer&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnixDomainSocketServer&nbsp;server&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;UnixDomainSocketServer(<br />
&nbsp;&nbsp;&nbsp;&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;">/home/dennis/time</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;UnixDomainSocket.SOCK_STREAM);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;output&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;server.getOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;date&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Date();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateFormat&nbsp;dateFormat&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SimpleDateFormat(</span><span style="color: #000000;">"</span><span style="color: #000000;">yyyy-MM-dd&nbsp;HH:mm:ss</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output.write(dateFormat.format(date).getBytes());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(IOException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 通过<span style="color: #000000;">UnixDomainSocketServer创建server，指定类型为SOCK_STREAM，juds也支持UDP类型。client的使用如下:<br />
</span>
<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: #0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte</span><span style="color: #000000;">[]&nbsp;b&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[</span><span style="color: #000000;">128</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">UnixDomainSocketClient&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;UnixDomainSocketClient("/home/dennis/time",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnixDomainSocket.SOCK_STREAM);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;socket.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in.read(b);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Text&nbsp;received:&nbsp;\</span><span style="color: #000000;">""</span><span style="color: #000000;">&nbsp;+&nbsp;new&nbsp;String(b)&nbsp;+&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">\</span><span style="color: #000000;">""</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();</span></div>
&nbsp;&nbsp;&nbsp; 显然，juds还只支持阻塞IO，考虑可进一步使用select、poll来扩展实现非阻塞IO。<br />
<br />
&nbsp;&nbsp;&nbsp; 最后一个例子，通过juds访问memcached的unix domain socket，简单的version协议调用：<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: #0000ff;">byte</span><span style="color: #000000;">[]&nbsp;b&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[</span><span style="color: #000000;">128</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnixDomainSocketClient&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;UnixDomainSocketClient(</span><span style="color: #000000;">"</span><span style="color: #000000;">/home/dennis/memcached</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnixDomainSocket.SOCK_STREAM);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;socket.getOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;text&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">version\r\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(text.getBytes());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;socket.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in.read(b);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Text&nbsp;received:&nbsp;\</span><span style="color: #000000;">""</span><span style="color: #000000;">&nbsp;+&nbsp;new&nbsp;String(b)&nbsp;+&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">\</span><span style="color: #000000;">""</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();</span></div>
&nbsp;&nbsp; 输出<br />
&nbsp;&nbsp;&nbsp;&nbsp; Text received: "VERSION 1.4.1"<br /><img src ="http://www.blogjava.net/killme2008/aggbug/298301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-10-15 06:12 <a href="http://www.blogjava.net/killme2008/archive/2009/10/15/298301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE_Select_Reactor在win32上编译的小问题</title><link>http://www.blogjava.net/killme2008/archive/2009/02/03/253089.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 03 Feb 2009 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/02/03/253089.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/253089.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/02/03/253089.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/253089.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/253089.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; ACE_Reactor在windows上默认不是使用ACE_Select_Reactor，而是ACE_WFMO_Reactor（封装了WaitForMultipleObjects和WSAEventSelect）。如果想选择ACE_Select_Reactor，如：<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;">ACE_Select_Reactor&nbsp;select_reactor;<br />
ACE_Reactor&nbsp;reactor&nbsp;(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">select_reactor);</span></div>
<br />
&nbsp;&nbsp;&nbsp; 那么VC需要启用/GR编译选项，具体做法就是在项目属性c/c++的语言一栏中启用RTTI信息即可。在选择了ACE_Select_Reactor之后，启动进程后在ProcessExplorer果然可以看到进程的TCP属性中建立了两个互连的TCP连接，用以notify的实现。<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/select_reactor.jpg" alt="" border="0" /><br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/253089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-02-03 15:40 <a href="http://www.blogjava.net/killme2008/archive/2009/02/03/253089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE Reactor的Echo Server</title><link>http://www.blogjava.net/killme2008/archive/2009/02/03/253057.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 03 Feb 2009 03:59:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/02/03/253057.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/253057.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/02/03/253057.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/253057.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/253057.html</trackback:ping><description><![CDATA[相对完整的修改版本<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: #008080;">&nbsp;&nbsp;1</span>&nbsp;<span style="color: #008000;">/*</span><span style="color: #008000;">***********************************************************************&nbsp;<br />
</span><span style="color: #008080;">&nbsp;&nbsp;2</span>&nbsp;<span style="color: #008000;">*&nbsp;@file:&nbsp;echo.cpp&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;&nbsp;3</span>&nbsp;<span style="color: #008000;">*&nbsp;@author:&nbsp;dennis<br />
</span><span style="color: #008080;">&nbsp;&nbsp;4</span>&nbsp;<span style="color: #008000;">*&nbsp;@revise:&nbsp;dennis&nbsp;&lt;killme2008@gmail.com&gt;&nbsp;</span><span style="color: #008000; text-decoration: underline;">http://www.blogjava.net/killme2008</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;5</span>&nbsp;<span style="color: #008000;">*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;相对完整的echo&nbsp;server，可以接受多个客户端连接，并且可以通过键入quit正常关闭<br />
</span><span style="color: #008080;">&nbsp;&nbsp;6</span>&nbsp;<span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;7</span>&nbsp;<span style="color: #008000;">***********************************************************************</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;8</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;9</span>&nbsp;<span style="color: #000000;">#ifdef&nbsp;_DEBUG<br />
</span><span style="color: #008080;">&nbsp;10</span>&nbsp;<span style="color: #000000;">#pragma&nbsp;comment&nbsp;(lib,</span><span style="color: #000000;">"</span><span style="color: #000000;">aced.lib</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;11</span>&nbsp;<span style="color: #0000ff;">#else</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;12</span>&nbsp;<span style="color: #000000;">#pragma&nbsp;comment&nbsp;(lib,</span><span style="color: #000000;">"</span><span style="color: #000000;">ace.lib</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;13</span>&nbsp;<span style="color: #0000ff;">#endif</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;14</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;15</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ace/Reactor.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;16</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ace/SOCK_Acceptor.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;17</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ace/os.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;18</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ace/Log_Msg.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;19</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ace/inet_addr.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;20</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ace/Thread_Manager.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;21</span>&nbsp;<span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">iostream</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;22</span>&nbsp;<span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;23</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;24</span>&nbsp;<span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;PORT_NO 8080</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;25</span>&nbsp;<span style="color: #000000;">typedef&nbsp;ACE_SOCK_Acceptor&nbsp;Acceptor;<br />
</span><span style="color: #008080;">&nbsp;26</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">forward&nbsp;declaration</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;27</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Echo_Handler;<br />
</span><span style="color: #008080;">&nbsp;28</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;29</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Echo_Handler:</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ACE_Event_Handler<br />
</span><span style="color: #008080;">&nbsp;30</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">&nbsp;31</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">:<br />
</span><span style="color: #008080;">&nbsp;32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">construcor</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Echo_Handler()<br />
</span><span style="color: #008080;">&nbsp;34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">~</span><span style="color: #000000;">Echo_Handler()<br />
</span><span style="color: #008080;">&nbsp;37</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;38</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;39</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Called&nbsp;back&nbsp;to&nbsp;handle&nbsp;any&nbsp;input&nbsp;received</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;40</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;handle_input(ACE_HANDLE)<br />
</span><span style="color: #008080;">&nbsp;41</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;42</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">receive&nbsp;the&nbsp;data</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;43</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssize_t&nbsp;recvBytes&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;peer().recv(data,</span><span style="color: #000000;">12</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(recvBytes&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;45</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;46</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_DEBUG,</span><span style="color: #000000;">"</span><span style="color: #000000;">%s\n</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;">));<br />
</span><span style="color: #008080;">&nbsp;47</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;48</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;49</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[recvBytes]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;50</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;51</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_DEBUG,</span><span style="color: #000000;">"</span><span style="color: #000000;">%s\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,data));<br />
</span><span style="color: #008080;">&nbsp;52</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;53</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;54</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(ACE_OS::strcmp(data,</span><span style="color: #000000;">"</span><span style="color: #000000;">q</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;55</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;56</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_DEBUG,</span><span style="color: #000000;">"</span><span style="color: #000000;">%s\n</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;">));<br />
</span><span style="color: #008080;">&nbsp;57</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer().close();<br />
</span><span style="color: #008080;">&nbsp;58</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;59</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;60</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer().send_n(data,recvBytes);<br />
</span><span style="color: #008080;">&nbsp;61</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;do&nbsp;something&nbsp;with&nbsp;the&nbsp;input&nbsp;received.<br />
</span><span style="color: #008080;">&nbsp;62</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;<br />
</span><span style="color: #008080;">&nbsp;63</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;keep&nbsp;yourself&nbsp;registerd&nbsp;with&nbsp;the&nbsp;reator</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;64</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;65</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;66</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;67</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;handle_close(ACE_HANDLE&nbsp;h,ACE_Reactor_Mask&nbsp;m)<br />
</span><span style="color: #008080;">&nbsp;68</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;69</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;70</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;71</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;72</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;73</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Used&nbsp;by&nbsp;the&nbsp;reactor&nbsp;to&nbsp;determine&nbsp;the&nbsp;underlying&nbsp;handle</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;74</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_HANDLE&nbsp;get_handle()&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #008080;">&nbsp;75</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;76</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">peer_.get_handle();<br />
</span><span style="color: #008080;">&nbsp;77</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;78</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;79</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Returns&nbsp;a&nbsp;reference&nbsp;to&nbsp;the&nbsp;underlying&nbsp;stream.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;80</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_SOCK_Stream</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;peer()<br />
</span><span style="color: #008080;">&nbsp;81</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;82</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">peer_;<br />
</span><span style="color: #008080;">&nbsp;83</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;84</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;85</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">:<br />
</span><span style="color: #008080;">&nbsp;86</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_SOCK_Stream&nbsp;peer_;<br />
</span><span style="color: #008080;">&nbsp;87</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;data&nbsp;[</span><span style="color: #000000;">12</span><span style="color: #000000;">];<br />
</span><span style="color: #008080;">&nbsp;88</span>&nbsp;<span style="color: #000000;">};<br />
</span><span style="color: #008080;">&nbsp;89</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;90</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Echo_Accept_Handler:</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ACE_Event_Handler<br />
</span><span style="color: #008080;">&nbsp;91</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">&nbsp;92</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">:<br />
</span><span style="color: #008080;">&nbsp;93</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Constructor</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;94</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Echo_Accept_Handler(ACE_Addr&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">addr)<br />
</span><span style="color: #008080;">&nbsp;95</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;96</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">open(addr);<br />
</span><span style="color: #008080;">&nbsp;97</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;98</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">~</span><span style="color: #000000;">Echo_Accept_Handler(){}<br />
</span><span style="color: #008080;">&nbsp;99</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Open&nbsp;the&nbsp;peer_acceptor&nbsp;so&nbsp;it&nbsp;starts&nbsp;to&nbsp;"listen"<br />
</span><span style="color: #008080;">100</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">for&nbsp;incoming&nbsp;clients</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">101</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;open(ACE_Addr&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">addr)<br />
</span><span style="color: #008080;">102</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">103</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(peer_acceptor.open(addr)</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">104</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_ERROR_RETURN((LM_ERROR,</span><span style="color: #000000;">"</span><span style="color: #000000;">启动服务器错误\n</span><span style="color: #000000;">"</span><span style="color: #000000;">),</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">105</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">106</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">107</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">108</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Overload&nbsp;the&nbsp;handle&nbsp;input&nbsp;method</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">109</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;handle_input(ACE_HANDLE&nbsp;handle)<br />
</span><span style="color: #008080;">110</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">111</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Client&nbsp;has&nbsp;requested&nbsp;connection&nbsp;to&nbsp;server.<br />
</span><span style="color: #008080;">112</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Create&nbsp;a&nbsp;handler&nbsp;to&nbsp;handle&nbsp;the&nbsp;connection</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">113</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Echo_Handler&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">eh;<br />
</span><span style="color: #008080;">114</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_NEW_RETURN(eh,Echo_Handler,</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">115</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_INET_Addr&nbsp;cliaddr;<br />
</span><span style="color: #008080;">116</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Accept&nbsp;the&nbsp;connection&nbsp;"into"&nbsp;the&nbsp;Event&nbsp;Handler</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">117</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">peer_acceptor.accept(eh</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">peer(),</span><span style="color: #008000;">//</span><span style="color: #008000;">stream</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">118</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">cliaddr,</span><span style="color: #008000;">//</span><span style="color: #008000;">remote&nbsp;address</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">119</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,</span><span style="color: #008000;">//</span><span style="color: #008000;">timeout</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">120</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)</span><span style="color: #008000;">//</span><span style="color: #008000;">restart&nbsp;if&nbsp;interrupted</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">121</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_ERROR,</span><span style="color: #000000;">"</span><span style="color: #000000;">Error&nbsp;in&nbsp;connection&nbsp;\n</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
</span><span style="color: #008080;">122</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">123</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_DEBUG,</span><span style="color: #000000;">"</span><span style="color: #000000;">连接已经建立,来自%s\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,cliaddr.get_host_addr()));<br />
</span><span style="color: #008080;">124</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">125</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Register&nbsp;the&nbsp;input&nbsp;event&nbsp;handler&nbsp;for&nbsp;reading&nbsp;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">126</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor::instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">register_handler(eh,ACE_Event_Handler::READ_MASK);<br />
</span><span style="color: #008080;">127</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;msg&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">按q键使服务安全退出\r\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">128</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eh</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">peer().send_n(msg,strlen(msg)</span><span style="color: #000000;">+</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">129</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">130</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">131</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">132</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Used&nbsp;by&nbsp;the&nbsp;reactor&nbsp;to&nbsp;determine&nbsp;the&nbsp;underlying&nbsp;handle</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">133</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_HANDLE&nbsp;get_handle(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">134</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">135</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">peer_acceptor.get_handle();<br />
</span><span style="color: #008080;">136</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">137</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;handle_close(ACE_HANDLE&nbsp;h,ACE_Reactor_Mask&nbsp;m){<br />
</span><span style="color: #008080;">138</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer_acceptor.close();<br />
</span><span style="color: #008080;">139</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">140</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">141</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">142</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">143</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">:<br />
</span><span style="color: #008080;">144</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Acceptor&nbsp;peer_acceptor;<br />
</span><span style="color: #008080;">145</span>&nbsp;<span style="color: #000000;">};<br />
</span><span style="color: #008080;">146</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Quit_Handler:</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ACE_Event_Handler<br />
</span><span style="color: #008080;">147</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">148</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">:<br />
</span><span style="color: #008080;">149</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Quit_Handler(ACE_Reactor</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;r):ACE_Event_Handler(r){}<br />
</span><span style="color: #008080;">150</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;handle_exception(ACE_HANDLE)<br />
</span><span style="color: #008080;">151</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">152</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_DEBUG,</span><span style="color: #000000;">"</span><span style="color: #000000;">停止服务器中<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />\n</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
</span><span style="color: #008080;">153</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reactor()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">end_reactor_event_loop();<br />
</span><span style="color: #008080;">154</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">155</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">156</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;handle_close(ACE_HANDLE&nbsp;h,ACE_Reactor_Mask&nbsp;m)<br />
</span><span style="color: #008080;">157</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">158</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">159</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">160</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">161</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">~</span><span style="color: #000000;">Quit_Handler(){}<br />
</span><span style="color: #008080;">162</span>&nbsp;<span style="color: #000000;">};<br />
</span><span style="color: #008080;">163</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ACE_THR_FUNC_RETURN&nbsp;run_events&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">arg);<br />
</span><span style="color: #008080;">164</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ACE_THR_FUNC_RETURN&nbsp;controller&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">arg);<br />
</span><span style="color: #008080;">165</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;ACE_TMAIN(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">argv[])<br />
</span><span style="color: #008080;">166</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">167</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">168</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;reactor</span><span style="color: #000000;">=</span><span style="color: #000000;">ACE_Reactor::instance();<br />
</span><span style="color: #008080;">169</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(ACE_Thread_Manager::instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">spawn(run_events,reactor,THR_DETACHED&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;THR_SCOPE_SYSTEM)</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">170</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">171</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(ACE_Thread_Manager::instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">spawn(controller,reactor,THR_DETACHED&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;THR_SCOPE_SYSTEM)</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">172</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">173</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ACE_Thread_Manager::instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">wait();<br />
</span><span style="color: #008080;">174</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">175</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">176</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ACE_THR_FUNC_RETURN&nbsp;run_events&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">arg)<br />
</span><span style="color: #008080;">177</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">178</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;reactor</span><span style="color: #000000;">=</span><span style="color: #000000;">ACE_static_cast(ACE_Reactor</span><span style="color: #000000;">*</span><span style="color: #000000;">,arg);<br />
</span><span style="color: #008080;">179</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_INET_Addr&nbsp;addr(PORT_NO);<br />
</span><span style="color: #008080;">180</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">181</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Echo_Accept_Handler&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">eh</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">182</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_NEW_RETURN(eh,Echo_Accept_Handler(addr),</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">183</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">184</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor::instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">owner(ACE_OS::thr_self());<br />
</span><span style="color: #008080;">185</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;reactor</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">register_handler(eh,ACE_Event_Handler::ACCEPT_MASK);<br />
</span><span style="color: #008080;">186</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor::instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">run_reactor_event_loop();<br />
</span><span style="color: #008080;">187</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">188</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">189</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ACE_THR_FUNC_RETURN&nbsp;controller&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">arg)<br />
</span><span style="color: #008080;">190</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">191</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;reactor</span><span style="color: #000000;">=</span><span style="color: #000000;">ACE_static_cast(ACE_Reactor</span><span style="color: #000000;">*</span><span style="color: #000000;">,arg);<br />
</span><span style="color: #008080;">192</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Quit_Handler&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">quit_handler</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">193</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ACE_NEW_RETURN(quit_handler,Quit_Handler(reactor),</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">194</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(;;)<br />
</span><span style="color: #008080;">195</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">196</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;line;<br />
</span><span style="color: #008080;">197</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::getline(std::cin,line,</span><span style="color: #000000;">'</span><span style="color: #000000;">\n</span><span style="color: #000000;">'</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">198</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(line</span><span style="color: #000000;">==</span><span style="color: #000000;">"</span><span style="color: #000000;">quit</span><span style="color: #000000;">"</span><span style="color: #000000;">){<br />
</span><span style="color: #008080;">199</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_DEBUG((LM_DEBUG,</span><span style="color: #000000;">"</span><span style="color: #000000;">请求停止服务器\n</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
</span><span style="color: #008080;">200</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reactor</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">notify(quit_handler);<br />
</span><span style="color: #008080;">201</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">202</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">203</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">204</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">205</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">206</span>&nbsp;</div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/253057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-02-03 11:59 <a href="http://www.blogjava.net/killme2008/archive/2009/02/03/253057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>