Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2033478
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: C/C++

2007-12-29 23:02:30

以前用perl写的一个网络程序,最近运行的时候频繁出错,tcpdump抓包分析的结果是连接没能正常关闭,因为连接是用RST中止的。

review了n次代码,除了正常的socket调用外,并没有显式设置SO_LINGER等socket选项;为了防止perl语言在后台偷偷地做些地下操作,又用strace跟踪了脚本的系统调用,同样也并没有发现任何异常;接着又用C语言重写了脚本逻辑,现象和perl的版本完全一致。排除了语言的差异,只能从操作系统着手分析了。

虽然Linux内核源码就在手边,但是不到万不得已,决不轻易碰触,看来今天是在所难免了。翻阅了TCP包接收部分的代码,没有发现任何异样。再次没了方向,联想到RST抢占的是FIN的位置,因此不妨从tcp_close入手分析,在其中发现可疑注释和代码:

    /* As outlined in draft-ietf-tcpimpl-prob-03.txt, section
     * 3.10, 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(LINUX_MIB_TCPABORTONCLOSE);
        tcp_set_state(sk, TCP_CLOSE);
        tcp_send_active_reset(sk, GFP_KERNEL);


data_was_unread是在用close关闭socket的时候,仍然缓冲在socket缓冲区没被应用程序读取的数据的字节数,如果它不是0,则表示有些数据本端的应用程序没有收到,也就是网络传输出现了“故障”,因此用RST将这一情况通告给对端,而不是用FIN报告一切正常。从注释来看,此种情况下,老版本的内核确实是发送FIN的,文档的3.10小节详细分析了这个tcp实现问题。看来当时我用来测试的Linux内核的确够古老...

那么为什么会发生数据没有读完全的情况呢?为此,查阅了perl手册页中对recv的解释:

Returns the address of the sender if SOCKET's protocol
               supports this; returns an empty string otherwise.  If there's an
               error, returns the undefined value.

这个函数的返回值让我大吃一惊,它的返回值与C语言接口中的recv的返回值简直是大相径庭,如此的不一致,以至于不能想当然,你说我能不汗颜么?

问题找到了,有的放矢的修补自然就轻松的很了!

通过这件事,我觉得有的时候我们还是笨一点儿好,不要为了可能的那么一点点儿“便利”,就挺而走险;还有就是对待不是很清楚的东西一定要注意,不要被表象所迷惑,不能想当然;perl中recv的这种不一致性也需要为此负责,所以我们以后做类似的事情的时候,尽可能要保证不标新立异,照顾到用户的望文生义和想当然!
阅读(2094) | 评论(2) | 转发(0) |
0

上一篇:用户级线程的抢占

下一篇:新年

给主人留下些什么吧!~~

xiaosuo2008-01-02 08:47:50

新年快乐!

BenBear2008-01-02 08:45:42

小锁强悍~~ 新年快乐~