libhv踩坑记(一)

关于libhv框架我这里就不做描述了,这里有作者本人的介绍https://blog.csdn.net/gg_simida/category_9866493.html

我主要做一些在使用libhv时遇到的一些问题。好,入正题。

我的libhv框架是在2021年1月10日从github:https://github.com/ithewei/libhv/上下载下来的,并且非Debug编译生成了静态库来使用的。

编译环境:win10专业版+cmake3.19.2 x64+vs 2019

先放入我的测试代码

服务端:

// server.cpp: 定义应用程序的入口点。
//

#include <iostream>
#include <hv/hloop.h>

static void on_close(hio_t* io)
{
    std::cout << io << "  ---> disconnect" << std::endl;
}

static void on_recv(hio_t* io, void* buf, int readbytes)
{
    const char* data = reinterpret_cast<const char*>(buf);
    std::string s(data, static_cast<std::size_t>(readbytes));
    std::cout << s << std::endl;
}

static void heartbeat_callback(hio_t* io)
{

}

static void on_accept(hio_t* io)
{
    std::cout << io << "  ---> connect" << std::endl;
    hio_setcb_close(io, on_close);
    hio_setcb_read(io, on_recv);
    hio_set_heartbeat(io, 1500, heartbeat_callback);
    hio_set_keepalive_timeout(io, 5000);
    hio_read(io);
}

int main()
{
    hloop_t* loop = hloop_new();
    hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", 20000, on_accept);

    if (listenio == NULL)
    {
        return -20;
    }

    int fd = hio_fd(listenio);

    std::cout << "start loop" << std::endl;
    hloop_run(loop);
    hloop_free(&loop);
    std::cout << "process end" << std::endl;

    system("pause");
	return 0;
}

客户端:

#include <iostream>
#include <hv/hloop.h>

static hio_t* stdinio = NULL;
// for socket
static hio_t* sockio = NULL;

#define RECV_BUFSIZE    8192
static char recvbuf[RECV_BUFSIZE];

void on_recv(hio_t* io, void* buf, int readbytes) {
    //printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
    printf("%.*s", readbytes, (char*)buf);
    fflush(stdout);
}

static void heartbeat_callback(hio_t* io)
{

}

static void connect_callback(hio_t *io)
{
    std::cout << "connect success" << std::endl;

    hio_set_heartbeat(io, 1500, heartbeat_callback);
    hio_set_keepalive_timeout(io, 5000);

    const char* msg = "hello";

    hio_write(io, msg, strlen(msg));
}
void on_stdin(hio_t* io, void* buf, int readbytes) {
    //printf("on_stdin fd=%d readbytes=%d\n", hio_fd(io), readbytes);
    //printf("> %s\n", buf);

    char* str = (char*)buf;

    // test hio_read_start/hio_read_stop/hio_close/hloop_stop
    if (strncmp(str, "start", 5) == 0) {
        printf("call hio_read_start\n");
        hio_read_start(sockio);
        return;
    }
    else if (strncmp(str, "stop", 4) == 0) {
        printf("call hio_read_stop\n");
        hio_read_stop(sockio);
        return;
    }
    else if (strncmp(str, "close", 5) == 0) {
        printf("call hio_close\n");
        hio_close(sockio);
        return;
    }
    else if (strncmp(str, "quit", 4) == 0) {
        printf("call hloop_stop\n");
        hloop_stop(hevent_loop(io));
        return;
    }

    // CR|LF => CRLF for test most protocols
    char eol = str[readbytes - 1];
    if (eol == '\n' || eol == '\r') 
    {
        if (readbytes > 1 && str[readbytes - 2] == '\r' && eol == '\n') 
        {
            // have been CRLF
        }
        else 
        {
            ++readbytes;
            str[readbytes - 2] = '\r';
            str[readbytes - 1] = '\n';
        }
    }

    hio_write(sockio, buf, readbytes);
}

void on_close(hio_t* io) 
{
    //printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
    hio_del(stdinio, HV_READ);
}

int main()
{
    hloop_t* loop = hloop_new(HLOOP_FLAG_QUIT_WHEN_NO_ACTIVE_EVENTS);

    // stdin use default readbuf
    stdinio = hread(loop, 0, NULL, 0, on_stdin);
    if (stdinio == NULL) {
        return -20;
    }

    int name_len = 256;
    char hostname[256]{ 0 };
    gethostname(hostname, name_len);
    sockio = hloop_create_tcp_client(loop, hostname, 20000, connect_callback);

    if (sockio == NULL)
    {
        std::cout << "process error" << std::endl;
        system("pause");
        return 0;
    }

    hio_setcb_close(sockio, on_close);
    hio_setcb_read(sockio, on_recv);
    hio_set_readbuf(sockio, recvbuf, RECV_BUFSIZE);

    hloop_run(loop);
    hloop_free(&loop);

    std::cout << "process end" << std::endl;

    system("pause");
	return 0;
}

测试步骤:

1. 开启服务端,进入监听状态,控制台输出结果:

2. 开启客户端,控制台输出结果

问题分析:

从客户端输出来看,hloop_create_tcp_client函数返回了空值,好,看看源码查看究竟

结合控制台的输出“socket: No such file or directory”知道,打印这一行错误的是893行,也就是创建socket套接字失败了,在确认了参数没问题之后,初步得出判断是没有调用WSAStartup()启动命令。再看libhv框架源码确认是否没有调用(如有兴趣,可自行查询源码,我这里就略过了)

①从客户端代码入手,看一下hloop_new源码

初始化事件循环,底层并没有启动WSA的命令。

②hread是把控制台输入添加到事件循环当中,也没有启动WSA命令。

③hloop_create_tcp_client把创建套接字以及连接服务端都封装在一起,也是没有启动WSA命令的。

尝试解决:

如果没有调用WSAStartup(),则我自行添加,查看libhv源码获得参数

新增后客户端源码main函数改为:

启动测试:

客户端输出:

服务端输出:

自此,问题就解决了!! 

如有问题,欢迎指出。

猜你喜欢

转载自blog.csdn.net/qq811299838/article/details/113149119