﻿<?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-DiveInto-文章分类-NetWork</title><link>http://www.blogjava.net/mmliu/category/44766.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 03 May 2010 06:49:20 GMT</lastBuildDate><pubDate>Mon, 03 May 2010 06:49:20 GMT</pubDate><ttl>60</ttl><item><title>Silly Window Syndrom[窗口犯傻综合症]  {TCP相关}</title><link>http://www.blogjava.net/mmliu/articles/319904.html</link><dc:creator>mmLiu</dc:creator><author>mmLiu</author><pubDate>Sun, 02 May 2010 14:37:00 GMT</pubDate><guid>http://www.blogjava.net/mmliu/articles/319904.html</guid><wfw:comment>http://www.blogjava.net/mmliu/comments/319904.html</wfw:comment><comments>http://www.blogjava.net/mmliu/articles/319904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mmliu/comments/commentRss/319904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mmliu/services/trackbacks/319904.html</trackback:ping><description><![CDATA[<p>早期的TCP实现,本来是为了 提高传输效率&amp;&amp;控制传输速率 而存在的滑动窗口[Sliding window] 机制,在发送方和接收方 生产和消耗数据的速率差异较大时,会产生一种比较犯傻的传输状态:发送方发送的数据报文[Segment] 具有一个大大的头部,附带的数据却少得可怜.<br />
<br />
<span style="font-size: 18pt"><span style="font-size: 14pt"><strong style="font-size: 14pt">犯傻症的产生<br />
</strong></span></span><br />
考虑以下两种情况:<br />
&nbsp;&nbsp;&nbsp; 1.接收方的应用程序读取数据老慢老慢,一次只1byte.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以想见,很快,接收方的缓存被填满,于是回发窗口通告[window advtisement]说:已满,勿发.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;接下来,应用程序慢吞吞的读入1byte,缓存空余出来一字节,兴高采烈的再次回发窗口通告说:一字节可用,快来填满我.<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; 然后,如此重复.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;很明显,这样不好,效率太低. 一般TCP报文头部大小最少也是<a style="background-color: #99cc00" href="http://www.2808c.cn/wljs/wljczs/04168487.shtml">20字节</a>,结果只拖这么点数据过去,头部的处理(校验和的计算,流的序列号的读取,数据的提取),到IP数据报的封装及相应的解封 又要照行不误,实在效率忒也底下了.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;2.相应的是发送方的应用程序,产出数据慢,一次一字节,一字节一个报文,也会导致效率问题.<br />
<br />
<span style="font-size: 14pt"><strong><span style="font-size: 18pt"><span style="font-size: 14pt"><strong><span style="font-size: 24pt"><strong style="font-size: 14pt"><strong>犯傻症的</strong>防治</strong></span></strong></span></span><br />
</strong>&nbsp;&nbsp;<span style="font-size: 18pt"><span style="font-size: 10pt">&nbsp;</span><span style="font-size: 14pt"><span style="font-size: 12pt"><span style="font-size: 10pt">1.接收方<br />
</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 12pt"><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.对每一个到达的TCP报文回送ACK,但在窗口的空余增大到指定大小之前,我都不会报告窗口的大小,免得回送一个1byte,你就想也不想就发个报文过来.</span></span></span><span style="font-size: 12pt"><br />
<span style="font-size: 12pt"><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.或者,延迟ACK的发送.并不一定对每个TCP报文都回送ACK,而是每个报文到达后,稍等片刻.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 12pt"><span style="font-size: 12pt"><span style="font-size: 10pt">&nbsp;</span></span><span style="font-size: 12pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><strong>Adventage</strong>:<br />
</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.减少交通流量.一个ACK可能对多个报文做出确认回复,不用一一回复啦.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.Piggyback. 当接收方收到数据后需要回送数据时,可以在回送数据的TCP报文中<strong>捎带[piggyback</strong>] ACK确认,同样减少了网络流量.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp;窗口通告[window advertizement]是在数据于缓冲区被读取后才发出的,这和对应的报文的到达时间有一定延后,而ACK的延迟发送就可能等待到窗口大小的改变，两者一起回发（又是piggyback?）,同样减少了数据流量.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><strong>Disadventage</strong></span>:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.报文重传时间是根据报文来回时间推测而来的.ACK延迟策略影响了对合理重传时间的判断,本来一秒钟就到了的,结果延迟设定的时间太夸张,用了十秒,这边的传送方就说那好吧,就15秒吧,15秒还不到我就算你报文丢失了,直接结果就是反应迟钝,正常的5秒钟就可以判定丢失的,偏要等到15秒,好难等啊...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.另外,延迟时间太夸张了,最直接的结果就是发送方等啊等,没等到,干脆重传了(其实那报文早到了,没回送确认而已),这样添加了无谓的重传,增加网络负担.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 14pt"><span style="font-size: 12pt"><span style="font-size: 10pt">&nbsp; </span></span><span style="font-size: 12pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><strong>Solve</strong>:<br />
</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相应的解决方法简单得很,既然都是延迟时间太夸张导致的,我就把延迟时间设个上限呗,现在的建议是0.5秒.<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;<span style="font-size: 10pt">&nbsp;2.发送方&nbsp;<strong>&nbsp;</strong></span><span style="font-size: 18pt"><strong>&nbsp;</strong></span>&nbsp;&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;<span style="font-size: 10pt">想象一下,为了避免传输小数据报,可以让TCP稍等一会儿,待到数据聚集多后,一起发送,嗯,想法不错,不过等多少时间呢?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.5秒?50秒?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关键是TCP应对的对象是多种多样滴,可以是人,是打字快的人,是半小时打一个字的打字慢的人,是5M/S的文件传输.....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对人,0.5秒太短,对文件传输,时间又太长.故时间的选择是一个问题.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 想一种自适应的策略出来.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.对打字慢的人来讲,不应该强行奢望说每个报文都携带大量数据,不然应用程序延迟太大,聊QQ我打一行字不一定有20byte呢,结果你强行说100byte我再给你发,我不是很郁闷.所以这种情况理想下应该及时发送,相比人的慢速,网络的ACK是到的快的,所以但凡ACK到达,我就发送下一数据报,而不理睬是否报文数据达到一定大小(这样就没有提高传输效率一说了,不过程序嘛,当然用户体验第一啦,小牺牲一下效率也是值得滴).<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.对传输大户比如文件传输呢?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还发一个报文,乖乖等ACK然后再发下一个就太慢了吧,乖乖,我可是10M/S的速度写入啊,这时就应该藐视ACK,只要缓冲区数据写入填满了最大报文,就立刻发送,毫不等待(当然了,还是得遵循滑动窗口的限制吧,<span style="color: red">猜测,待确认</span>).<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而兼容以上两种情况的策略就诞生了:<br />
</span><br />
</span></span><span style="text-align: center; widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 22px; font-family: Arial, Helvetica, sans-serif; color: rgb(61,61,61); font-size: 14px" class="Apple-style-span"></p>
<p style="padding-bottom: 0px; line-height: 22px; margin: 0cm 0cm 0pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><font style="line-height: 25px" size="3"><span style="font-size: 12pt"><span style="font-size: 10pt"><span><font style="line-height: 25px"><span style="line-height: 25px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em> </em>1 .</span><span class="Apple-converted-space">&nbsp;对从应用程序收到的第一块数据,</span></font>发送端的</span><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px">TCP</font></span><span style="line-height: 25px; font-family: 宋体">直接将它发送出去，哪怕只有一个字节。</span></span></span></font></p>
<p style="padding-bottom: 0px; line-height: 22px; margin: 0cm 0cm 0pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><font style="line-height: 25px" size="3"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px"><span style="line-height: 25px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2</span><span class="Apple-converted-space">&nbsp;.此</span></font></span><span style="line-height: 25px; font-family: 宋体">后，发送端的</span><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px">TCP</font></span><span style="line-height: 25px; font-family: 宋体">就在输出缓存中积累数据，并等待：或者接收端的</span><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px">TCP</font></span><span style="line-height: 25px; font-family: 宋体">发送出一个确认，或者数据已积累到可以装成一个最大的报文段。二者满足其一，发送端的</span><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px">TCP</font></span><span style="line-height: 25px; font-family: 宋体">就可以发送这个报文段。</span></span></span></font></p>
<p style="padding-bottom: 0px; line-height: 22px; margin: 0cm 0cm 0pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><font style="line-height: 25px" size="3"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px"><span style="line-height: 25px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.</span></font></span><span style="line-height: 25px; font-family: 宋体">对剩下的传输，重复步骤</span><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px">2</font></span><span style="line-height: 25px; font-family: 宋体">。这就是：如果收到了对报文段</span><span style="line-height: 25px" lang="EN-US"><font style="line-height: 25px">x</font></span><span style="line-height: 25px; font-family: 宋体">的确认，或者数据已积累到可以装成一个最大的报文段，那么就发送下一个报文段</span></span></span><span><span style="font-size: 12pt"><span style="font-size: 10pt"><font style="line-height: 25px">(x + 1)</font>。<br />
<br />
&nbsp;&nbsp; (我看的《Intenetworking with TCP/IP》中，作者评价这个策略是Surpring and Elegant.赞赏之情溢于言表.</span></span></span></font></p>
</span></span>
<p><br />
<br />
<br />
<br />
<br />
<br />
&nbsp;</p>
</span></span>
 <img src ="http://www.blogjava.net/mmliu/aggbug/319904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mmliu/" target="_blank">mmLiu</a> 2010-05-02 22:37 <a href="http://www.blogjava.net/mmliu/articles/319904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络中基本传输单元的命名:Frame Datagram Segment and Packet</title><link>http://www.blogjava.net/mmliu/articles/319895.html</link><dc:creator>mmLiu</dc:creator><author>mmLiu</author><pubDate>Sun, 02 May 2010 11:52:00 GMT</pubDate><guid>http://www.blogjava.net/mmliu/articles/319895.html</guid><wfw:comment>http://www.blogjava.net/mmliu/comments/319895.html</wfw:comment><comments>http://www.blogjava.net/mmliu/articles/319895.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mmliu/comments/commentRss/319895.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mmliu/services/trackbacks/319895.html</trackback:ping><description><![CDATA[<br />
不同的网络层对应不同的传输单元,自上而下:<br />
<br />
&nbsp; <span style="color: red">TCP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>(Transport layer 传输层)&nbsp;&nbsp;==&gt; <span style="color: red">Segment&nbsp; </span>[报文]<br />
&nbsp;&nbsp;&nbsp; <span style="color: red">IP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(Network layer 网际层)&nbsp;&nbsp; ==&gt; <span style="color: red">Datagram&nbsp; </span>[数据报]<br />
<span style="color: red">Ethernet&nbsp;&nbsp; </span>(Link layer&nbsp; 链路层)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&gt; <span style="color: red">Frame&nbsp;&nbsp;</span>[帧]<br />
<br />
另外,存在一个泛称,通指所有层的基本传输单元:<br />
<br />
&nbsp; <span style="color: red">Packet </span>[分组]<br />
<br />
<br />
更多可以参考<a style="background-color: #99cc00" href="http://www.nsrc.org/workshops/2004/SANOG-IV/ip-services/presentations/ip-intro/ipbasics/sld013.htm">这里</a>. 
<img src ="http://www.blogjava.net/mmliu/aggbug/319895.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mmliu/" target="_blank">mmLiu</a> 2010-05-02 19:52 <a href="http://www.blogjava.net/mmliu/articles/319895.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>