<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[qu1993的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/qu1993</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; qu1993]]></copyright><item><title><![CDATA[hio_write]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111768107</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111768107</guid><author>qu1993</author><pubDate>Sun, 27 Dec 2020 12:43:48 +0800</pubDate><description><![CDATA[之前的博客已经提到发送数据要比接收数据难，因为发送数据时主动的，接收数据是被动的。而且因为libhv采用的是level trigger，因此只有在需要时才关注writeable事件，否则就会造成busy loop。原因可以参考上一篇博客。


int hio_write (hio_t* io, const void* buf, size_t len) {
    //判断io是否处于关闭状态
    if (io-&gt;closed) {
        hloge("hio_write called b]]></description><category></category></item><item><title><![CDATA[水平触发和边缘触发]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111550425</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111550425</guid><author>qu1993</author><pubDate>Sun, 27 Dec 2020 12:43:19 +0800</pubDate><description><![CDATA[水平触发比较常见，例如select、poll等都是水平触发的，而epoll不仅支持水平触发，也支持边缘触发。实际工作学习中我从未见过使用边缘触发开发的网络程序，但是之前在《Linux多线程服务端编程》这本书中，陈硕大神有一段话：我认为理想的做法是对readable事件采用level trigger，对writable事件采用edge trigger，但是目前Linux不支持这种设定。边缘触发的读还比较好理解，但是写到底是如何工作的，感觉不是太好理解，所以今天写了个测试程序想验证下之前的理解对不对，这篇博客也]]></description><category></category></item><item><title><![CDATA[创建一个简单的tcp客户端]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111408095</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111408095</guid><author>qu1993</author><pubDate>Sun, 20 Dec 2020 20:06:51 +0800</pubDate><description><![CDATA[因为上一篇写创建tcp服务端已经把很多重要接口分析过了，这一篇会写的比较简单。

与创建tcp服务端类似，创建一个客户端的步骤如下：


    hloop_t* loop = hloop_new(HLOOP_FLAG_QUIT_WHEN_NO_ACTIVE_EVENTS); //创建一个loop
    hio_t* sockio = hloop_create_tcp_client(loop, host, port, on_connect);

    hio_setcb_close(sockio, on]]></description><category></category></item><item><title><![CDATA[创建一个简单的TCP服务器]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111256021</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111256021</guid><author>qu1993</author><pubDate>Sat, 19 Dec 2020 12:43:52 +0800</pubDate><description><![CDATA[以tcp_echo_server.c为例，说明创建tcp服务器的程序流程。


int main(int argc, char** argv) {
    if (argc &lt; 2) {
        printf("Usage: tcp port\n");
        return -10;
    }
    int port = atoi(argv[1]);

    hloop_t* loop = hloop_new(0); //创建一个loop
    //创建一个用来监听的io，用来]]></description><category></category></item><item><title><![CDATA[custom事件]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111297130</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111297130</guid><author>qu1993</author><pubDate>Thu, 17 Dec 2020 12:48:38 +0800</pubDate><description><![CDATA[libhv提供了一个接口，可以由用户自己添加事件，接口为：


// NOTE: hloop_post_event is thread-safe
HV_EXPORT void hloop_post_event(hloop_t* loop, hevent_t* ev);

首先看下该接口的实现


void hloop_post_event(hloop_t* loop, hevent_t* ev) {
    char buf = '1';

    if (loop-&gt;sockpair[0] == -]]></description><category></category></item><item><title><![CDATA[idle事件]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111275642</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111275642</guid><author>qu1993</author><pubDate>Wed, 16 Dec 2020 16:26:48 +0800</pubDate><description><![CDATA[在libhv中，除了支持IO事件和定时器事件，还有idle和custom两种事件。idle比较简单，下一篇再分析custom。idle空闲事件，即在空闲时处理的事件

libhv提供了两个接口操作idle事件


//添加idle事件
HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
//删除idle事件
HV_EXPORT void     hidle_del(hidle]]></description><category></category></item><item><title><![CDATA[heartbeat和keepalive]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111246515</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111246515</guid><author>qu1993</author><pubDate>Wed, 16 Dec 2020 10:59:14 +0800</pubDate><description><![CDATA[libhv提供了设置心跳和保活机制的接口


HV_EXPORT void hio_set_heartbeat(hio_t* io, int interval_ms, hio_send_heartbeat_fn fn);
HV_EXPORT void hio_set_keepalive_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_KEEPALIVE_TIMEOUT));

在分析源码之前，先说下通过心跳机制的重要意义，首先，可以通过检测心跳可以]]></description><category></category></item><item><title><![CDATA[定时器的简单说明]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111197841</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111197841</guid><author>qu1993</author><pubDate>Tue, 15 Dec 2020 12:44:43 +0800</pubDate><description><![CDATA[对任何一个网络库，定时器功能都非常重要，libhv当然也不例外，今天先对目前我所使用的定时器功能做一个简单说明。

libhv主要提供了三个接口使用定时器，添加、删除和重置，还有一个htimer_add_period，目前没用过，先不说了。。。。


htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint32_t timeout, uint32_t repeat DEFAULT(INFINITE));
void htimer_del(htimer_t* ]]></description><category></category></item><item><title><![CDATA[事件的优先级机制]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/111194770</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/111194770</guid><author>qu1993</author><pubDate>Tue, 15 Dec 2020 11:58:10 +0800</pubDate><description><![CDATA[在libhv库中，可以对各种事件设置不同的优先级，库提供了一个设置宏，可以简单设置。


#define hevent_set_priority(ev, prio)   ((hevent_t*)(ev))-&gt;priority = prio

使用方法很简单，而且在hloop_test.c测试文件中有使用例子，不再多说，下面简单说下libhv对不同优先级事件的处理方式

在hloop_process_events接口中，处理各种事件，其中定时器是具有最高优先级的，在libhv中，如果存在定时器任务，会优]]></description><category></category></item><item><title><![CDATA[宏定义黑魔法]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110956384</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110956384</guid><author>qu1993</author><pubDate>Fri, 11 Dec 2020 14:27:24 +0800</pubDate><description><![CDATA[1、


#define CLR_RED         "\033[31m"      /* 红色字 */
#define CLR_GREEN       "\033[32m"      /* 绿色字 */
#define CLR_YELLOW      "\033[33m"      /* 黄色字 */
#define CLR_BLUE        "\033[34m"      /* 蓝色字 */
#define CLR_PURPLE      "\033[35m"      /* 紫色字 */
.]]></description><category></category></item><item><title><![CDATA[heap.h]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110855013</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110855013</guid><author>qu1993</author><pubDate>Tue, 08 Dec 2020 12:28:43 +0800</pubDate><description><![CDATA[上一篇写了写链表，这篇写下堆，这个结构接触的不多，所以正好学习一下libhv中的堆，这个堆的实现比较灵活，即可以是大顶堆也可以是小顶堆，通过比较函数是比大还是比小来区别，当然，如果没有比较函数，就成了无序的，感觉没啥意义，就不讨论无序的堆了。

堆的定义

堆是具有下列性质的完全二叉树：每个结点的值都大于或等于其左右孩子结点的值，称为大顶堆；或者每个结点的值都小于或等于其左右孩子结点的值，称为小顶堆。

完全二叉树是啥就不解释了。。。。。 下面开始看代码

结构体定义


struct heap_node ]]></description><category></category></item><item><title><![CDATA[list.h]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110731150</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110731150</guid><author>qu1993</author><pubDate>Sun, 06 Dec 2020 13:46:06 +0800</pubDate><description><![CDATA[在libhv库中，有一个双向链表的实现，刚看的时候感觉有点疑惑，因为这个链表没有数据，只有前指针和后指针，跟过去学的不太一样，于是仔细分析了一下。

首先是结构体：


struct list_head {
	struct list_head *next, *prev;
};
#define list_node   list_head

该结构体不包含数据信息。

下面的初始化：


static inline void list_init(struct list_head *list)
{
	list-&]]></description><category></category></item><item><title><![CDATA[简单的单进程的网络流量监控程序]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110686103</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110686103</guid><author>qu1993</author><pubDate>Sat, 05 Dec 2020 15:08:02 +0800</pubDate><description><![CDATA[前一篇博客说了nethogs的一些问题，因为nethogs无法满足我的需求，所以自己写了一个，因为对libpcap库和网络协议了解有限，所以可能存在一些问题。目前该程序只支持指定PID的进程网络流量监控，支持TCP和UDP，输出的信息包括：1s的平均流量、10s的每秒平均流量、60s的每秒平均流量、从监控开始的总的流量。代码如下：

decpcap.c和decpcap.h是nethogs封装的接口，直接拿来用了。。。。

decpcap.c


#include "decpcap.h"
#include &]]></description><category></category></item><item><title><![CDATA[nethogs的局限性]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110676955</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110676955</guid><author>qu1993</author><pubDate>Sat, 05 Dec 2020 10:36:13 +0800</pubDate><description><![CDATA[之前想找一个可以监视系统进程网络流量的工具，网上都推荐使用nethogs，我在自己的linux系统上安装了nethogs，感觉还挺好用的，但是当我在公司的服务器上运行的时候就会出现各种问题，有时候会卡死，有时候虽然不卡死，显示的信息也不太对，奇奇怪怪，但是又很想用这个功能，于是阅读了下nethogs的源码，发现了一些问题，应该是该工具存在一些局限性。

我所谓的局限性主要体现在 当服务器上都大量的网络连接，也就是短连接比较多的情况，nethogs就无法正常工作了。而我是用的服务器恰恰有比较多的短连接，导致该]]></description><category></category></item><item><title><![CDATA[vscode远端无法追踪代码以及如何使用VSIX]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110558602</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110558602</guid><author>qu1993</author><pubDate>Thu, 03 Dec 2020 18:09:58 +0800</pubDate><description><![CDATA[今天配置vscode 的远端功能后，无法追踪代码，而且有个报错，显示：Downloading package ‘C/C++ language components (Windows)‘ Failed. Retrying... Failed. Retrying...

解决办法是从https://github.com/microsoft/vscode-cpptools/releases这里下载需要的包



然后使用vscode的从VSIX安装，左键扩展旁边的三个点，就可以看到从VSIX安装，之后选择刚...]]></description><category></category></item><item><title><![CDATA[超简单计算器的C++实现，只支持加减乘除和括号]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/110124752</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/110124752</guid><author>qu1993</author><pubDate>Wed, 25 Nov 2020 13:29:14 +0800</pubDate><description><![CDATA[#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;stack&gt;
#include &lt;vector&gt;
#include &lt;map&gt;
#include &lt;assert.h&gt;
using namespace std;

string strip(const string &amp;s, const string &amp;chars = "")
{
    if (s.empty())
    .]]></description><category></category></item><item><title><![CDATA[桥接模式--结构型模式]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/109667949</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/109667949</guid><author>qu1993</author><pubDate>Wed, 25 Nov 2020 08:37:15 +0800</pubDate><description><![CDATA[1、描述

桥接是一种结构型模式，可将业务逻辑或一个大类拆分成为不同的层次结构，从而能独立的进行开发。

层次结构中的第一层（通常称为抽象部分）将包含对第二层（实现部分）对象的引用。抽象部分能将一些（有时是绝大部分）对自己的调用委派给实现部分的对象。所有的实现部分都有一个通用接口，因此他们能在抽象部分内部相互替换。

2、结构图



Abstraction：提供高层控制逻辑，依赖于完成底层实际工作的实现对像
	Implementation：为所有具体实现声明通用接口。抽象部分仅能通过在这里声明的方法与实现]]></description><category></category></item><item><title><![CDATA[享元模式--结构型模式]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/109677659</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/109677659</guid><author>qu1993</author><pubDate>Tue, 24 Nov 2020 18:11:08 +0800</pubDate><description><![CDATA[1、描述

2、结构图

3、C++代码
]]></description><category></category></item><item><title><![CDATA[状态模式--行为模式]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/109820283</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/109820283</guid><author>qu1993</author><pubDate>Tue, 24 Nov 2020 16:17:24 +0800</pubDate><description><![CDATA[1、描述

状态是一种行为设计模式，让你能在一个对象的内部状态变化时改变其行为。

该模式将与状态相关的行为抽取到独立的状态类中，让原对象将工作委派给这些类的实例，而不是自行进行处理。

2、结构图



3、C++代码


#include &lt;iostream&gt;
#include &lt;typeinfo&gt;

class Context;

//状态基类声明了一些所有的具体状态类都需要实现的方法；并且提供了一个与状态关联的Context对象
//的回溯引用。状态类使用该回溯引用转换到其他]]></description><category></category></item><item><title><![CDATA[访问者模式--行为模式]]></title><link>https://blog.youkuaiyun.com/qu1993/article/details/109891737</link><guid>https://blog.youkuaiyun.com/qu1993/article/details/109891737</guid><author>qu1993</author><pubDate>Tue, 24 Nov 2020 15:17:14 +0800</pubDate><description><![CDATA[1、描述

访问者是一种行为设计模式，允许你在不修改已有代码的清空下向已有类层次结构中添加新的行为。

2、结构图



3、C++代码


#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;array&gt;
/**
 * The Visitor Interface declares a set of visiting methods that correspond to
 * component classes. The sig]]></description><category></category></item></channel></rss>