关于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
#include
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(buf);
std::string s(data, static_cast(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
#include
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函数改为:
启动测试:
客户端输出:
服务端输出:
自此,问题就解决了!!
如有问题,欢迎指出。