一开始,我得向Libuv库和Libuv库开发者以及相关粉丝们道一个歉,对不起,我错怪你们了。深深感到自己的无知,是多么羞愧的事情!!
    事情的经过是这样的。
    原先按照公司要求,我在开发Windows版的TCP服务器时,使用了Libuv库。正是因为Libuv库的强大,才让我们老大推荐使用。我们老大学识渊博,阅历丰富,他的推荐自然也是很值得使用的。所以我快速学习了一下Libuv库的使用。然后再学习的过程中,稍有了解。同时发现了一个网友phata写的对于Libuv库的包装,让代码写起来更加方便。当然,他是针对Windows版的包装。我用了之后,也就大大加快了开发的速度。对此,我非常感谢网友phata。也正是这些网友的无私,将一些宝贵的代码分享出来,才促进了开发的发展,让学习开发变得容易。所以我一直坚持分享的习惯,也正是更多是受益于各路网友的分享,我学有所成,我也希望将我的经验和成果分享给更多人。互联网的共享互助精神大概如此吧。C++技术网就是我分享我所有经验的平台,希望更多人能够参与进来吧。
    Windows版的服务器做好之后,后来又需要Linux版的服务器。所以,直接将libuv使用在了Linux的Centos发行版上了。phata编写的Windows版本libuv封装类,我进行了精简整理,发布在C++技术网。然后我再将这个精简后的版本,改成了Linux版本,并应用在了Linux版的服务器上。Linux版的Libuv封装类的代码见《基于libuv封装的TCP通信类-服务端类源代码》。在这个文章里,你可以找到其他相关的代码。
    然而好景不长,在后续的测试中发现了一个问题:客户端发送一个数据到服务器后,服务器单次回复一次数据,一切正常。但是收到一个数据,连续回复两次数据时,不管是间隔1秒还是10秒,都会造成线程死循环。这个问题持续了很久,而且只在Linux中表现出来。
    迟迟没有直接解决问题,所以后来就想到一个办法,就是将多个数据合并到一个数据,然后将多次发送做成了一次发送,这样就避开了问题。然而再后来出现的需求,让合并数据成为了不可能。两次发送数据,是两个线程完成的。但是有时候可能合并得到一起,有时候无法合并到一起,因为我还是想利用之前避开问题的方法来实现,结果效果很不理想。
    所以,在最开始出现连续两次发送数据造成死循环的时候,我将我上层的业务代码全部干掉,直接写测试代码,结果发现一样会出现死循环。这样之后,我就认定是Libuv的坑了。所以后来就只有饶坑了,心情很是不爽。
    按照其他同事的说法,Libuv是nodejs使用的,应该不会出现这么低级的问题吧。其实我也觉得不应该出现这么低级的问题,然而这个问题就在这,我都不知道为什么。只能先将锅甩给了libuv。
    当后面的需求,无法绕过去的时候,还是要直接面对这个坑的问题。怎么办呢?那就只能学习和深入研究源码了。最要命的是,Libuv的资料太少了,就有那么一本英文书,网络有人正在翻译为中文,还没有翻译完。而且这个书也不是那么全面,至少我读了之后,还是没有完全明白的意思,懵懵懂懂的。除了这个,基本上没有比较深入的资料了。要么是一点学习笔记,写了一个demo,无关痛痒。
    正是因为Libuv文档太少了,让学习Libuv变得困难,出现问题都无从查询资料。而源码,也不是谁都能够看懂的。我也不愿意去钻研源码,如果能够解决问题,绝不研究源码。如果是对源码本身感兴趣,那也是闲暇的时候研究,而工作比较紧张,没有那么多时间。
    事情已经进行到了必须面对问题的时候,所以我就开始再从仅有的少数资料里和代码里研究问题。然后也加了一个QQ群,群也就3个。对于示例代码的一个简单的问题,一个群友竟然说要500RMB才肯解答,说他研究了2年了。哎~ 我自己继续研究好了。

然后不断的调试代码,分析代码的流程,这次是直接使用libuv的测试代码研究,通过熟悉代码,测试,然后竟然成功的实现了连续两次服务器回复命令。2017年6月3日上午,实现了一个版本。然后晚上,又实现了另外一个版本。第一个版本比较凑合,第二个版本最接近于我使用的版本,也就是前面提到的改成Linux下的libuv包装类,其实和示例代码差不多。在这个示例测试中,直接连续两次发送数据,和项目中的问题一样。然后通过不懈的努力,然后成功实现了连续两次发送数据,依然正常运行。

到现在为止,我才真正明白我之前的问题所在了。问题不在libuv,也不在于网友phata的Windows版的libuv包装类,而是在于我改成linux版的libuv包装类。我忽略的一点就是,libuv在Windows上使用的是完成端口,而在linux上使用的是异步事件epoll。两者是不一样的,所以在改成linux版libuv包装类的时候,我没有做好处理,只是简单的改了一下,忽略了底层实现的差异,才出现了这个问题。所以在Windows上没有问题,在Linux有问题。我竟然直接根据这个判定libuv有这样一个低级的坑!可见我是多么无知。
    所以我总结一句话:完全相信权威,那是迷信;而不深入调查,仅根据表明现象就直接否定权威,那是无知!!
    我们经常听说不要完全相信权威,要敢于质疑权威,但是很多时候,我们却不知道,质疑权威应该如何质疑。正确的质疑是用实践去证明,用合理的证据证明权威是错的。而我这个行为,是没有经过深入的调查研究的,所以是无知的表现。还好,有这机会让我直接面对问题,让我查出问题的原因,让我反省,让我矫正自己的态度。

写下这篇文章,记录一下此时我的无知,在今后的研究路上,多一份谦逊,多一份研究,少一点无知,也用以警告我自己,不要随意下定论。

注:Linux版本的libuv包装类,你还是可以使用的,只是不要对一个请求回复多个命令。一对一的回复,这个包装类是可以用的。后面我再想办法改进,修复这个问题。所以分享的那个代码是可以用,只是要注意这个问题。

原文链接

我应该跟libuv说声对不起,我错怪了libuv(转)的更多相关文章

  1. 从今天起,正式步入cnblogs,向曾经的脚印说声对不起!

    步入这个行业也好多年了,从来没有定居过一个地方. 看过很多前辈们留下的资料,对后者门(其中还有我)留下很多珍贵的东西. 所以,我要向前辈学习,壮大自己,在学习的同时,不要忘记帮助别人. 对曾经我留下的 ...

  2. linux下libuv库安装教程

    下载并编译libuv libuv需要自己手动下载源码,并手动编译. 当前目录为:/home/xlz/test/github,在后面,会用$PATH来代替,我的系统的Debian8,64bit. $gi ...

  3. 网络开发库从libuv说到epoll

    引言 这篇博文可能有点水,主要将自己libuv的学习过程和理解. 简单谈方法. 有点杂. 那我们开始吧. 首先介绍 githup . 这个工具特别好用. 代码托管. 如果不FQ可能有点卡. 但是应该试 ...

  4. Microsoft Visual Studio 2017 编译最新版 libuv 1.x

    步骤很简单 1 下载最新版的 libuv(地址:https://github.com/libuv 2 安装Git,Python 2.7 ,cmake(这里使用的是 3.11.0-win64-x64 版 ...

  5. 简单对比 Libevent、libev、libuv

    Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library). 异步事件库本质上是提供异步事件通知(Asynchronous Ev ...

  6. 报错libtest: error while loading shared libraries: libuv.so.1: cannot open shared object file: No such file or directory

    使用g++编译.运行libuv的demo错误解决 我们通过例子来讲述监视器的使用. 例子中空转监视器回调函数被不断地重复调用,  通过例子我们也可以了解到: 由于设置了监视器, 所以调用 uv_run ...

  7. 浅析libuv源码-编译启动

    面试的间隙回头复习了一下node,感觉node就像一个胶带,把V8和libuv粘在了一起. V8毫无疑问,负责解析执行JavaScript,相当于语言层面的桥梁:而libuv则是负责操作系统底层功能的 ...

  8. libuv 简单使用

    libuv 简单使用 来源:https://zhuanlan.zhihu.com/p/50497450 前序:说说为啥要研究libuv,其实在很久之前(大概2年前吧)玩nodejs的时候就对这个核心库 ...

  9. libuv之介绍

    本人是在研究linux下socket TCP/IP通讯时,用到了一些linux下的API,比如socket, connect, bind,listen, accept等等,简单写个点对点的通讯,直接用 ...

随机推荐

  1. ExtJS学习(四)EditorGrid可编辑表格

    操作表格有一种需求,要操作表格需要动态的添加内容,删除内容以及双击的时候进入编辑状态.这个时候怎么办呢,看具体的实现吧. 双击点击的时候可以单元格的操作. 代码: <!DOCTYPE html& ...

  2. printk的用法

    printk的用法 内核通过 printk() 输出的信息具有日志级别,日志级别是通过在 printk() 输出的字符串前加一个带尖括号的整数来控制的,如 printk("<6> ...

  3. 02-Git简单使用

    Git安装(windows) https://code.google.com/p/msysgit/downloads/list 我们使用版本Git-1.7.9版本 百度网盘下载:链接:http://p ...

  4. Android 优质精准的用户行为统计和日志打捞方案

    Android 自定义优质精准的用户行为和日志打捞方案 Tamic csdn博客 :http://blog.csdn.net/sk719887916/article/details/51398416 ...

  5. iOS中 HTTP/Socket/TCP/IP通信协议详解 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 简单介绍: // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 ...

  6. 【java虚拟机系列】java中类与对象的加载顺序

    首先了解一下Java虚拟机初始化的原理. JVM通过加装.连接和初始化一个Java类型,使该类型可以被正在运行的Java程序所使用.类型的生命周期如下图所示: 装载和连接必须在初始化之前就要完成. 类 ...

  7. CSS House

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 用SpriteBuilder简化"耕牛遍地走"的动画效果(三)

    接下来的代码和原文差不多,建立一个数组用来存放动画帧,然后用数组来初始化一个CCAnimation动画对象.接着将牛放在屏幕中心,然后运行动画: NSMutableArray *walkAnimFra ...

  9. 十大常见Java String问题

    翻译人员: 铁锚 翻译时间: 2013年11月7日 原文链接: Top 10 questions of Java Strings 本文介绍Java中关于String最常见的10个问题: 1. 字符串比 ...

  10. c语言和java的区别

    今晚读了一下c程序设计语言,这是一本经典书籍,发现C语言和java有很多是相同的,毕竟java是由c语言进化来的. 我大概从我自己的思考来谈谈不同点 1.c语言是面向过程,主要单位是函数,变量和函数的 ...