TCP滑动窗口易错处,后来者戒之!

    前段时间研究分布式时写了一个可扩展的服务器组程序,服务器组之间通信时老是达不到想要的性能。后来抓包排查,原来是TCP滑动窗口引起的问题,本来是很基础的东西,奈何当初没有太在意,导致错误的产生,现在详细写出来,忘不太清楚者警惕!
   滑动窗口的基本情况我有必要废话一下。TCP通信为了保证可靠性,每次发送的数据都需要得到对方的ACK才确认对方收到了(仅保证对方TCP接收缓冲收到数据了,但不保证对方应用程序取到数据了),这时如果每次发送一次就要停下来等着对方的ACK消息,显然是一种极大的资源浪费和低下的效率,这时就有了滑动窗口的出现。
发送方的滑动窗口维持着当前发送的帧序号,已发出去帧的计时器,接收方当前的窗口大小(由接收方ACK通知,大体等于接收缓冲大小-未处理的消息包),接收方滑动窗口保存的有已接收的帧信息、期待的下一帧的帧号等,至于滑动窗口的具体工作原理这里就不说了。
   一个socket有两个滑动窗口(一个sendbuf、一个recvbuf),两个窗口的大小是通过setsockopt函数设置的,现在问题就出在这里,通过抓包显示,设置的窗口大小没有生效,最后排查发现setsockopt函数是后来加上的,写到了listen函数的后面,这样每次accept出的socket并没有继承得到主socket设置的窗口大小,无语啊……
   解决办法:setsockopt函数提前到listen函数之前,这样在服务器程序启动监听前recvbuf就已经有了,accept后的链接得到的就是recvbuf了,启动程序运行,抓包显示窗口已经是指定的大小了。
   网络编程其实很简单,任何人都可以写出一套自己的服务器框架,但是细节决定成败,性能的高低有时候就是几个小细节决定的(当然这里说的这个问题是个编程错误,不属于可优化的细节问题)

posted on 2012-11-29 14:17 peakflys 阅读(5273) 评论(7)  编辑 收藏 引用 所属分类: 服务器

评论

# re: TCP滑动窗口易错处,后来者戒之![未登录] 2012-11-29 16:35 kaka

滑动窗口?这么翻的中文有点怪异吧。recvbuf和sendbuf不就是“接收缓冲区”和"发送缓冲区"么?  回复  更多评论   

# re: TCP滑动窗口易错处,后来者戒之! 2012-11-30 09:48 peakflys

呵呵,滑动窗口英文名称是“sliding-window”是TCP协议的一部分,因其大小根据对方的ACK来动态调整,故称之为滑动窗口,这个称呼应该是很贴切很形象的,并且目前几乎所有关于网络的书籍都会翻译成滑动窗口。recvbuf和sendbuf是为了说明程序中设置的buffer大小和滑动窗口的关系我特意加上去的,不然估计有不少人像我之前一个同事一样只知道设置接收缓冲区和发送缓冲区,而不知道它们真正执行的过程 @kaka  回复  更多评论   

# re: TCP滑动窗口易错处,后来者戒之![未登录] 2012-11-30 10:35 kaka

受教了~~ @peakflys  回复  更多评论   

# re: TCP滑动窗口易错处,后来者戒之![未登录] 2012-12-03 13:26 春秋十二月

不错 确实如此  回复  更多评论   

# re: TCP滑动窗口易错处,后来者戒之![未登录] 2012-12-24 04:41 Sunny

"仅保证对方TCP接收缓冲收到数据了,但不保证对方应用程序取到数据了".
ack可以保证app接收到了data. 如果app接收tcp的数据之前退出, tcp会恢复rst, 而非ack, 从而保证server明白, app没有收到data.  回复  更多评论   

# re: TCP滑动窗口易错处,后来者戒之! 2012-12-24 15:32 peakflys

ack是TCP机制提供的一种接收反馈,对端接收发送的数据包会自动反馈回一个ack,这个过程上层app是没有参与的,所以单从一个ack来看是不知道对端app有没有取到刚才传送的数据,但是也有一个办法可以大体上猜到对端的使用,就是根据多个ack反馈,由窗口大小的改变来揣测。举个例子,对端窗口大小为65530个字节,我现在传过去10个字节,对端回复一个ack,但是这个ack不代表刚才传的10个字节对端app已经取到,但是如果我现在再传10个字节,如果对端回复的ack中window大小是65520,这时我可以猜出刚才传的数据已经被对端app取到了,这也就是原文中的意思:对端反馈回来ack,只代表对端接收到了数据,不代表上层应用程序取到了数据。@Sunny
  回复  更多评论   

# re: TCP滑动窗口易错处,后来者戒之! 2013-12-01 14:29 Marvin

“一个socket有两个滑动窗口(一个sendbuf、一个recvbuf),两个窗口的大小是通过setsockopt函数设置的”
滑动窗口和 sendbuf/recvbuf 到底是不是一回事?滑动窗口是动态改变大小的,sendbuf/recv/buf 难道也是 动态改变大小?  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2012年11月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

导航

统计

公告

人不淡定的时候,就爱表现出来,敲代码如此,偶尔的灵感亦如此……

常用链接

留言簿(4)

随笔分类

随笔档案

文章档案

搜索

最新评论

阅读排行榜

评论排行榜