<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Erlang非业余研究 &#187; TCP</title>
	<atom:link href="http://blog.yufeng.info/archives/tag/tcp/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.yufeng.info</link>
	<description>Erlang系统深度探索和应用</description>
	<lastBuildDate>Tue, 17 Jan 2012 06:05:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>TCP链接主动关闭不发fin包奇怪行为分析</title>
		<link>http://blog.yufeng.info/archives/1401</link>
		<comments>http://blog.yufeng.info/archives/1401#comments</comments>
		<pubDate>Fri, 01 Jul 2011 09:40:47 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[Erlang探索]]></category>
		<category><![CDATA[网络编程]]></category>
		<category><![CDATA[fin]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[TCP]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=1401</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: TCP链接主动关闭不发fin包奇怪行为分析 问题描述： 多隆同学在做网络框架的时候，发现一条tcp链接在close的时候，对端会收到econnrest,而不是正常的fin包. 通过抓包发现close系统调用的时候，我端发出rst报文, 而不是正常的fin。这个问题比较有意思，我们来演示下： 我们往baidu的首页发了个http请求，百度会给我们回应报文的,我们send完立即调用close. 然后我们在另外一个终端开tcpdump抓包确认： 我们可以清楚的看到 R 19:19(0) ack 486 win 7504,发了个rst包，通过strace系统调用也确认erlang确实调用了close系统调用。 那为什么呢？ @淘宝雕梁，tcp协议栈专家回答了这个问题： 在net/ipv4/tcp.c:1900附近 代码里面写的很清楚，如果你的接收缓冲去还有数据，协议栈就会发rst代替fin. 我们再来验证一下： 这次我们把接收缓冲区里的东西拉干净了。 再看下tcpdump： 这次是发fin包了。 多隆同学再进一步，找出来之前squid client代码中不能理解的一句话： client_side.c 总算明白了这句话的意思了！ 小结：认真学习协议栈太重要了。 玩得开心！ Post Footer automatically generated by wp-posturl plugin for wordpress.]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/1401">TCP链接主动关闭不发fin包奇怪行为分析</a></p>
</div>
<p>问题描述：<br />
多隆同学在做网络框架的时候，发现一条tcp链接在close的时候，对端会收到econnrest,而不是正常的fin包.  通过抓包发现close系统调用的时候，我端发出rst报文, 而不是正常的fin。这个问题比较有意思，我们来演示下：<br />
<span id="more-1401"></span></p>
<pre class="brush: bash; title: ; notranslate">
$ erl
Erlang R14B03 (erts-5.8.4) 1 [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.4  (abort with ^G)
1&gt; {ok,Sock} = gen_tcp:connect(&quot;baidu.com&quot;, 80, [{active,false}]).
{ok,#Port&lt;0.582&gt;}
2&gt; gen_tcp:send(Sock, &quot;GET / HTTP/1.1\r\n\r\n&quot;).
ok
3&gt; gen_tcp:close(Sock).
ok
</pre>
<p>我们往baidu的首页发了个http请求，百度会给我们回应报文的,我们send完立即调用close.</p>
<p>然后我们在另外一个终端开tcpdump抓包确认：</p>
<pre class="brush: bash; title: ; notranslate">
$ sudo tcpdump port 80 -i bond0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 96 bytes
17:22:38.246507 IP my031089.sqa.cm4.tbsite.net.19500 &gt; 220.181.111.86.http: S 2228211568:2228211568(0) win 5840 &lt;mss 1460,sackOK,timestamp 2607833238 0,nop,wscale 7&gt;
17:22:38.284602 IP 220.181.111.86.http &gt; my031089.sqa.cm4.tbsite.net.19500: S 3250338304:3250338304(0) ack 2228211569 win 8190 &lt;mss 1436&gt;
17:22:38.284624 IP my031089.sqa.cm4.tbsite.net.19500 &gt; 220.181.111.86.http: . ack 1 win 5840
17:22:52.748468 IP my031089.sqa.cm4.tbsite.net.19500 &gt; 220.181.111.86.http: P 1:19(18) ack 1 win 5840
17:22:52.786855 IP 220.181.111.86.http &gt; my031089.sqa.cm4.tbsite.net.19500: . ack 19 win 5840
17:22:52.787194 IP 220.181.111.86.http &gt; my031089.sqa.cm4.tbsite.net.19500: P 1:179(178) ack 19 win 5840
17:22:52.787203 IP my031089.sqa.cm4.tbsite.net.19500 &gt; 220.181.111.86.http: . ack 179 win 6432
17:22:52.787209 IP 220.181.111.86.http &gt; my031089.sqa.cm4.tbsite.net.19500: P 179:486(307) ack 19 win 5840
17:22:52.787214 IP my031089.sqa.cm4.tbsite.net.19500 &gt; 220.181.111.86.http: . ack 486 win 7504
17:23:01.564358 IP my031089.sqa.cm4.tbsite.net.19500 &gt; 220.181.111.86.http: R 19:19(0) ack 486 win 7504
...
</pre>
<p>我们可以清楚的看到  R 19:19(0) ack 486 win 7504,发了个rst包，通过strace系统调用也确认erlang确实调用了close系统调用。<br />
那为什么呢？<a href="http://www.pagefault.info/?from=yufeng"> @淘宝雕梁</a>，tcp协议栈专家回答了这个问题：</p>
<p>在net/ipv4/tcp.c:1900附近</p>
<pre class="brush: cpp; title: ; notranslate">
...
 /* As outlined in RFC 2525, section 2.17, we send a RST here because
    * data was lost. To witness the awful effects of the old behavior of
    * always doing a FIN, run an older 2.1.x kernel or 2.0.x, start a bulk
    * GET in an FTP client, suspend the process, wait for the client to
    * advertise a zero window, then kill -9 the FTP client, wheee...
    * Note: timeout is always zero in such a case.
    */
   if (data_was_unread) {
      /* Unread data was tossed, zap the connection. */
      NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);
      tcp_set_state(sk, TCP_CLOSE);
      tcp_send_active_reset(sk, sk-&gt;sk_allocation);
..
</pre>
<p>代码里面写的很清楚，如果你的接收缓冲去还有数据，协议栈就会发rst代替fin.<br />
我们再来验证一下：</p>
<pre class="brush: bash; title: ; notranslate">
$ erl
Erlang R14B03 (erts-5.8.4) 1 [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.4  (abort with ^G)
1&gt; {ok,Sock} = gen_tcp:connect(&quot;baidu.com&quot;, 80, [{active,false}]).
{ok,#Port&lt;0.582&gt;}
2&gt; gen_tcp:send(Sock, &quot;GET / HTTP/1.1\r\n\r\n&quot;).
ok
3&gt; gen_tcp:recv(Sock,0).
{ok,&quot;HTTP/1.1 400 Bad Request\r\nDate: Fri, 01 Jul 2011 09:24:37 GMT\r\nServer: Apache\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n127\r\n&lt;!DOCTYPE HTML PUBLIC \&quot;-//IETF//DTD HTML 2.0//EN\&quot;&gt;\n&lt;HTML&gt;&lt;HEAD&gt;\n&lt;TITLE&gt;400 Bad Request&lt;/TITLE&gt;\n&lt;/HEAD&gt;&lt;BODY&gt;\n&lt;H1&gt;Bad Request&lt;/H1&gt;\nYour browser sent a request that this server could not understand.&lt;P&gt;\nclient sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /&lt;P&gt;\n&lt;/BODY&gt;&lt;/HTML&gt;\n\r\n0\r\n\r\n&quot;}
4&gt; gen_tcp:close(Sock).
ok
5&gt;
</pre>
<p>这次我们把接收缓冲区里的东西拉干净了。</p>
<p>再看下tcpdump：</p>
<pre class="brush: bash; title: ; notranslate">
...
17:36:07.236627 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: S 3086473299:3086473299(0) win 5840 &lt;mss 1460,sackOK,timestamp 2608642228 0,nop,wscale 7&gt;
17:36:07.274661 IP 123.125.114.144.http &gt; my031089.sqa.cm4.tbsite.net.9405: S 738551248:738551248(0) ack 3086473300 win 8190 &lt;mss 1436&gt;
17:36:07.274685 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: . ack 1 win 5840
17:36:10.295795 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: P 1:19(18) ack 1 win 5840
17:36:10.334280 IP 123.125.114.144.http &gt; my031089.sqa.cm4.tbsite.net.9405: . ack 19 win 5840
17:36:10.334547 IP 123.125.114.144.http &gt; my031089.sqa.cm4.tbsite.net.9405: P 1:179(178) ack 19 win 5840
17:36:10.334554 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: . ack 179 win 6432
17:36:10.334563 IP 123.125.114.144.http &gt; my031089.sqa.cm4.tbsite.net.9405: P 179:486(307) ack 19 win 5840
17:36:10.334566 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: . ack 486 win 7504
17:36:19.671374 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: F 19:19(0) ack 486 win 7504
17:36:19.709619 IP 123.125.114.144.http &gt; my031089.sqa.cm4.tbsite.net.9405: . ack 20 win 5840
17:36:19.709643 IP 123.125.114.144.http &gt; my031089.sqa.cm4.tbsite.net.9405: F 486:486(0) ack 20 win 5840
17:36:19.709652 IP my031089.sqa.cm4.tbsite.net.9405 &gt; 123.125.114.144.http: . ack 487 win 7504
...
</pre>
<p>这次是发fin包了。</p>
<p>多隆同学再进一步，找出来之前squid client代码中不能理解的一句话：<br />
client_side.c</p>
<pre class="brush: cpp; title: ; notranslate">
...
 /* prevent those nasty RST packets */
    {
        char buf[SQUID_TCP_SO_RCVBUF];
        while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) &gt; 0);
    }
...
</pre>
<p>总算明白了这句话的意思了！</p>
<p>小结：认真学习协议栈太重要了。</p>
<p>玩得开心！</p>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/1401/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>看图学TCP API以及状态变迁</title>
		<link>http://blog.yufeng.info/archives/203</link>
		<comments>http://blog.yufeng.info/archives/203#comments</comments>
		<pubDate>Thu, 28 Jan 2010 02:42:31 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[网络编程]]></category>
		<category><![CDATA[shift]]></category>
		<category><![CDATA[State]]></category>
		<category><![CDATA[TCP]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=203</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: 看图学TCP API以及状态变迁 Post Footer automatically generated by wp-posturl plugin for wordpress.]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/203">看图学TCP API以及状态变迁</a></p>
</div>
<p><a href="http://blog.yufeng.info/wp-content/uploads/2010/01/ddvshrpj_18c4drttfv.png"><img src="http://blog.yufeng.info/wp-content/uploads/2010/01/ddvshrpj_18c4drttfv-202x300.png" alt="" title="ddvshrpj_18c4drttfv"  class="alignnone size-medium wp-image-202" /></a>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/203/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

