<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[TCP连接的状态转换图深度剖析]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Thu, 25 Feb 2010 11:56:18 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	平时我们需要观察LVS与Client及RS之间TCP连接建立情况，你就需要深入了解一下建立连接的TCP三次握手和关闭连接的四次握手，举下面一个例子，你知道这些状态表示什么吗，下面的TCP连接状态图可以让你明白这一切，往下看吧<br/>root@LG181:/usr/local/lvs# ipvsadm&nbsp;&nbsp;-L -c &#124; grep SYN_RECV<br/>TCP 00:54&nbsp;&nbsp;SYN_RECV&nbsp;&nbsp;&nbsp;&nbsp;117.24.44.192:40171 58.61.166.143:http 172.16.62.98:http<br/>TCP 00:28&nbsp;&nbsp;SYN_RECV&nbsp;&nbsp;&nbsp;&nbsp;116.25.96.121:foliocorp 58.61.166.143:http 172.23.151.167:http<br/>TCP 00:59&nbsp;&nbsp;SYN_RECV&nbsp;&nbsp;&nbsp;&nbsp;121.11.248.233:13447 58.61.166.143:http 172.16.62.73:http<br/>root@LG181:/usr/local/lvs# ipvsadm&nbsp;&nbsp;-L -c &#124; grep FIN&#124;head -n 3<br/>TCP 01:43&nbsp;&nbsp;FIN_WAIT&nbsp;&nbsp;&nbsp;&nbsp;61.154.119.42:kazaa 58.61.166.143:http 172.16.62.98:http<br/>TCP 01:41&nbsp;&nbsp;FIN_WAIT&nbsp;&nbsp;&nbsp;&nbsp;220.169.169.255:eli 58.61.166.143:http 172.16.62.98:http<br/>TCP 01:18&nbsp;&nbsp;FIN_WAIT&nbsp;&nbsp;&nbsp;&nbsp;59.39.127.15:10487 58.61.166.143:http 172.16.62.97:http<br/>root@LG181:/usr/local/lvs# ipvsadm&nbsp;&nbsp;-L -c &#124; grep ESTA&#124; head -n 3<br/>TCP 01:21&nbsp;&nbsp;ESTABLISHED 124.230.6.91:sybasedbsynch 58.61.166.143:http 172.23.151.167:http<br/>TCP 09:11&nbsp;&nbsp;ESTABLISHED 116.21.129.16:19043 58.61.166.143:http 172.23.151.167:http<br/>TCP 14:35&nbsp;&nbsp;ESTABLISHED 124.229.50.133:49139 58.61.166.143:http 172.16.62.98:http<br/><a href="http://www.jackxiang.com/attachment.php?fid=66" target="_blank"><img src="http://www.jackxiang.com/attachment.php?fid=66" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><br/>状态：描述<br/>CLOSED：无连接是活动的或正在进行<br/>LISTEN：服务器在等待进入呼叫<br/>SYN_RECV：一个连接请求已经到达，等待确认<br/>SYN_SENT：应用已经开始，打开一个连接<br/>ESTABLISHED：正常数据传输状态<br/>FIN_WAIT1：应用说它已经完成<br/>FIN_WAIT2：另一边已同意释放<br/>ITMED_WAIT：等待所有分组死掉<br/>CLOSING：两边同时尝试关闭<br/>TIME_WAIT：另一边已初始化一个释放<br/>LAST_ACK：等待所有分组死掉<br/>这个图n多人都知道，它对排除和定位网络或系统故障时大有帮助，但是怎样牢牢地将这张图刻在脑中呢？那么你就一定要对这张图的每一个状态，及转换的过程有深刻地认识，不能只停留在一知半解之中。下面对这张图的11种状态详细解释一下，以便加强记忆！不过在这之前，先回顾一下TCP建立连接的三次握手过程，以及关闭连接的四次握手过程。<br/>1、建立连接协议（三次握手）<br/>（1）客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。<br/><br/>（2） 服务器端回应客户端的，这是三次握手中的第2个报文，这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应；同时又标志SYN给客户端，询问客户端是否准备好进行数据通讯。<br/><br/>（3） 客户必须再次回应服务段一个ACK报文，这是报文段3。<br/><br/>2、连接终止协议（四次握手）<br/>由于TCP连接是全双工的，因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动，一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭，而另一方执行被动关闭。<br/><br/>（1） TCP客户端发送一个FIN，用来关闭客户到服务器的数据传送（报文段4）。<br/>（2） 服务器收到这个FIN，它发回一个ACK，确认序号为收到的序号加1（报文段5）。和SYN一样，一个FIN将占用一个序号。<br/>（3） 服务器关闭客户端的连接，发送一个FIN给客户端（报文段6）。<br/>（4） 客户段发回ACK报文确认，并将确认序号设置为收到序号加1（报文段7）。<br/><br/>CLOSED: 这个没什么好说的了，表示初始状态。<br/><br/>LISTEN: 这个也是非常容易理解的一个状态，表示服务器端的某个SOCKET处于监听状态，可以接受连接了。<br/><br/>SYN_RCVD: 这个状态表示接受到了SYN报文，在正常情况下，这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态，很短暂，基本上用netstat你是很难看到这种状态的，除非你特意写了一个客户端测试程序，故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时，当收到客户端的ACK报文后，它会进入到ESTABLISHED状态。<br/><br/>SYN_SENT: 这个状态与SYN_RCVD遥想呼应，当客户端SOCKET执行CONNECT连接时，它首先发送SYN报文，因此也随即它会进入到了SYN_SENT状态，并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。<br/><br/>ESTABLISHED：这个容易理解了，表示连接已经建立了。<br/><br/>FIN_WAIT_1: 这个状态要好好解释一下，其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是：FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时，它想主动关闭连接，向对方发送了FIN报文，此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后，则进入到FIN_WAIT_2状态，当然在实际的正常情况下，无论对方何种情况下，都应该马上回应ACK报文，所以FIN_WAIT_1状态一般是比较难见到的，而FIN_WAIT_2状态还有时常常可以用netstat看到。<br/><br/>FIN_WAIT_2：上面已经详细解释了这种状态，实际上FIN_WAIT_2状态下的SOCKET，表示半连接，也即有一方要求close连接，但另外还告诉对方，我暂时还有点数据需要传送给你，稍后再关闭连接。<br/><br/>TIME_WAIT: 表示收到了对方的FIN报文，并发送出了ACK报文，就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下，收到了对方同时带FIN标志和ACK标志的报文时，可以直接进入到TIME_WAIT状态，而无须经过FIN_WAIT_2状态。<br/><br/>CLOSING: 这种状态比较特殊，实际情况中应该是很少见，属于一种比较罕见的例外状态。正常情况下，当你发送FIN报文后，按理来说是应该先收到（或同时收到）对方的ACK报文，再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后，并没有收到对方的ACK报文，反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢？其实细想一下，也不难得出结论：那就是如果双方几乎在同时close一个SOCKET的话，那么就出现了双方同时发送FIN报文的情况，也即会出现CLOSING状态，表示双方都正在关闭SOCKET连接。<br/><br/>CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢？当对方close一个SOCKET后发送FIN报文给自己，你系统毫无疑问地会回应一个ACK报文给对方，此时则进入到CLOSE_WAIT状态。接下来呢，实际上你真正需要考虑的事情是察看你是否还有数据发送给对方，如果没有的话，那么你也就可以close这个SOCKET，发送FIN报文给对方，也即关闭连接。所以你在CLOSE_WAIT状态下，需要完成的事情是等待你去关闭连接。<br/><br/>LAST_ACK: 这个状态还是比较容易好理解的，它是被动关闭一方在发送FIN报文后，最后等待对方的ACK报文。当收到ACK报文后，也即可以进入到CLOSED可用状态了。<br/><br/>最后有2个问题的回答，我自己分析后的结论（不一定保证100%正确）<br/><br/>1、 为什么建立连接协议是三次握手，而关闭连接却是四次握手呢？<br/><br/>这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后，它可以把ACK和SYN（ACK起应答作用，而SYN起同步作用）放在一个报文里来发送。但关闭连接时，当收到对方的FIN报文通知时，它仅仅表示对方没有数据发送给你了；但未必你所有的数据都全部发送给对方了，所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后，再发送FIN报文给对方来表示你同意现在可以关闭连接了，所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。<br/><br/>2、 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态？<br/><br/>这是因为：虽然双方都同意关闭连接了，而且握手的4个报文也都协调和发送完毕，按理可以直接回到CLOSED状态（就好比从SYN_SEND状态到ESTABLISH状态那样）；但是因为我们必须要假想网络是不可靠的，你无法保证你最后发送的ACK报文会一定被对方收到，因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文，而重发FIN报文，所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文.<br/>
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] TCP连接的状态转换图深度剖析]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>