我们先来聊一聊网络超时的概念。以及模拟网络超时对我们程序的必要性
要想了解怎样模拟网络超时的情况,我们须要先了解一下
为什么会网络超时呢
简单的说:就是你向服务端发送数据请求。然尔server没返回数据,或返回数据太慢导致未收到返回数据。
比方,你要下载一个东东,你向server发送下载这个东东的请求。但等了好长时间都没有收到server允许你接收下载数据的请求,所以也不能一直这样等下去。你的电脑就会报告网络超时。假设不是你的网络故障,那么就是对方server的问题。
我们知道在TCP建立连接的时候有3次握手的规则
1. client发送’SYN’给服务端
2. 服务端返回确认’SYN_ACK’给client
3. client终于确定’ACK’
在这3次握手的时间内。每一次都有可能网络会掉包,我们分析一下每一种掉包的情况:
1. SYN丢失第一次握手client发送SYN掉包的情况:这样的情况下。client发送的SYN丢失在网络中,没有得到确认。client的TCP会超时重发SYN。
发送7个SYN后等待一个超时时间(比如:127秒)。假设在这段时间内仍然没有收到ACK,则connect返回超时。
2. SYN-ACK丢失从client的角度来讲曾经面一种情况类似。
从服务端的角度来讲,由LISTEN状态进入SYN_REVD状态。服务端的TCP会重发SYN-ACK,直到超时。
SYN攻击正是利用这一原理。攻击方伪造大量的SYN包发送到server,server对收到的SYN包不断回应SYN-ACK,直到超时。这会浪费server大量的资源,甚至导致奔溃。对服务端的应用层来讲。什么也没有发生。由于TCP仅仅有在经过3次握手之后才回通知应用层,有新的连接到来。
3. ACK丢失这对服务端来讲与2同样。对于client来讲,由SYN_SENT状态进入了ESTABLISED状态,即连接成功了。连接成功后client就能够发送数据了。
但实际上数据是发送不到服务端的(我们如果client收到SYN-ACK之后,client与服务端之间的网络就断开了),client发送出去的数据得不到确认。一般重发3次左右就会处于等待ACK的状态(win7)。而ubuntu 12.10下,调用send会返回成功。直到TCP的缓冲被填满(測试环境:局域网。感觉这个不是非常合理。依照书上所说:应该是使用“指数退避”进行重传 -- TCP/IP协议具体解释,大概是我的測试环境中有NAT所致
吧)。
终于。client产生一个复位信号并终止连接。
返回给应用程序的结果是Connection time out(errno: 110)
好,理解了3次握手掉包的情况下,我们就非常easy实现模拟超时情况的发生。
我们能够在port上控制服务端无法与client握手成功来让超时的情况发生
详细的实现要用到 iptables 这个命令
iptables-A OUTPUT -p tcp -m tcp --tcp-flags SYN SYN --sport 9090 -j DROP
这个命令是用来drop 掉响应SYN的返回
之前我们看到第一次客服端向server请求SYN的握手信息。而这个命令就是阻止server返回SYN_ACK的确认握手信息,这样client就无法收到服务端的握手确认信息了.
上面这样的情况是模拟连接没有成功的情况
以下另一种情况。就是连接已经成功了,可是在数据传输的时候,服务端没有及时返回数据,我们来看看这样的情况是怎样模拟的:
iptables -A OUTPUT -p tcp -m tcp --tcp-flags PSH PSH --sport 9090 -j DROP
细心的童鞋会发现,这里用到的flags 是PSH ,对。PSH的意思是控制信息是能够正常传送的,也就是说握手是正常成功的,然后数据传输的时候,我们限制了server无法给client传送数据内容,这样就模拟了连接是成功的。可是无法正常读取到服务端的数据的超时情况了
上面说的是最简单手动设置超时的方式,当然还有神器能够使用,接着就献上这款神器名叫netem,地址在
http://www.linuxfoundation.org/collaborate/workgroups/networking/netem
Network Emulation 有兴趣的童鞋能够前往研究。
Gerry
文章转自于小张网校博客
http://www.xiaozhangwx.com/blog/archives/73
阅读原文