wlgq2 / uv-cpp Goto Github PK
View Code? Open in Web Editor NEWlibuv wrapper in C++11 /libuv C++11网络库
License: MIT License
libuv wrapper in C++11 /libuv C++11网络库
License: MIT License
cy-2020-03-25
对于write中的buf是不是有要求free的时机?
1.Sever及EventLoop退出机制。
2.UDP组播。
tcp,udp 绑定地址和端口都没有判断是否成功,希望留个接口做判断绑定的地址是否成功
如题
客户端:
int main()
{
//定义事件分发器类
EventLoop* loop = new EventLoop();
#if TEST_IPV6
SocketAddr addr2("0:0:0:0:0:0:0:1", 10002, SocketAddr::Ipv6);
#else
SocketAddr addr2("127.0.0.1", 10002, SocketAddr::Ipv4);
#endif
LiteTcpClient client(loop);
client.connectToServer(addr2);
#if 1
//跨线程发送数据
std::thread thread([&client]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
char* data = new char[4]{ 't','e','s','t' };
while (1) {
client.write(data, sizeof(data));
}
});
#endif
loop->run();
服务端:
class LiteTcpServer :public uv::TcpServer
{
public:
LiteTcpServer(uv::EventLoop* loop)
:TcpServer(loop)
{
setMessageCallback(std::bind(&LiteTcpServer::newMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
private:
void newMessage(uv::TcpConnectionPtr connection, const char* buf, ssize_t size)
{
//不使用buffer
if (uv::GlobalConfig::BufferModeStatus == uv::GlobalConfig::NoBuffer)
{
std::cout << "receive data :" << std::string(buf, size) << std::endl;
char msg[255] = "Hello,I am Server";
#if 1 //直接发送
//connection->write(buf, size, nullptr);
connection->write(msg, sizeof(msg), nullptr);
。。。。
我在ubuntu20.04 下用 CodeBlocks跑了一下,好像tcpServer的内存一直没有释放掉,请问一下你那里测试有发现这个情况吗?
这段代码是什么语义呢,为什么每定时器触发一次就清空一次连接对象呢
void TimerWheel::wheelCallback()
{
if(!timeoutSec_)
return;
if(++index_ ==timeoutSec_)
{
index_=0;
}
wheel[index_].clear();
}
[EventLoop.h]
Line36: DefalutLoop() ->DefaultLoop();
Line42: hanlde() -> handle();
[Timer.h]
Line43: colseComplete() -> closeComplete();
可以提供下工程文件或者CMake文件吗
packet中size为uint16_t存放数据长度是否太小? 如果传递数据大于0xFFFF不能一次发送完.
linux的崩溃
#0 0x0000000000592310 in ?? ()
#1 0x00000000004f52dc in uv__io_poll (loop=0x578c60 <default_loop_struct>, timeout=161) at /mnt/hgfs/workspace/metel_sdp/client/third_party/libuv-1.42.0/src/unix/epoll.c:374
#2 0x00000000004e1a28 in uv_run (loop=0x578c60 <default_loop_struct>, mode=UV_RUN_DEFAULT) at /mnt/hgfs/workspace/metel_sdp/client/third_party/libuv-1.42.0/src/unix/core.c:389
#3 0x00000000004d5b80 in uv::EventLoop::run (this=0x578a20 uv::EventLoop::DefaultLoop()::defaultLoop) at /mnt/hgfs/workspace/metel_sdp/client/third_party/uv-cpp1.5.4/uv/EventLoop.cpp:67
#4 0x00000000004153c6 in main () at /mnt/hgfs/workspace/metel_sdp/client/sdp/app/main.cpp:99
#5 0x00007ffff6be7555 in __libc_start_main (main=0x414f30
在ubuntu下,我cmake和make之后,生成了libuv_cpp.a静态库,然后我用vscode编译一个helloworld例子,要怎么链接这些库?
vscode的tasks配置文件写成了如下:
但是这样做之后,他还是不能成功的编译出可执行文件,并且报错:EventLoop.cpp:(.text+0x2e):对‘uv_default_loop’未定义的引用
,这一系列的链接失败的错误码。
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-I","/home/aoa/Downloads/uv-cpp-master",
"-I","/home/aoa/Downloads/uv-cpp-master/libuv1.30.0/include",
"-L","/home/aoa/Downloads/uv-cpp-master/build",
"-l","uv_cpp",
"-Wl,-rpath=/home/aoa/Downloads/uv-cpp-master/build",
"-std=c++11",
"-Wall",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
/home/aoa/Downloads/uv-cpp-master/build/libuv_cpp.a(EventLoop.cpp.o):在函数‘uv::EventLoop::~EventLoop()’中:
EventLoop.cpp:(.text+0x2e):对‘uv_default_loop’未定义的引用
EventLoop.cpp:(.text+0x3c):对‘uv_loop_close’未定义的��用
/home/aoa/Downloads/uv-cpp-master/build/libuv_cpp.a(EventLoop.cpp.o):在函数‘uv::EventLoop::EventLoop(uv::EventLoop::Mode)’中:
EventLoop.cpp:(.text+0xbd):对‘uv_default_loop’未定义的引用
EventLoop.cpp:(.text+0x112):对‘uv_loop_init’未定义的引用
/home/aoa/Downloads/uv-cpp-master/build/libuv_cpp.a(EventLoop.cpp.o):在函数‘uv::EventLoop::run()’中:
EventLoop.cpp:(.text+0x1fd):对‘uv_run’未定义的引用
/home/aoa/Downloads/uv-cpp-master/build/libuv_cpp.a(EventLoop.cpp.o):��函数‘uv::EventLoop::runNoWait()’中:
EventLoop.cpp:(.text+0x250):对‘uv_run’未定义的引用
/home/aoa/Downloads/uv-cpp-master/build/libuv_cpp.a(EventLoop.cpp.o):在函数‘std::_Function_handler<void (uv::Async*), uv::EventLoop::stop()::{lambda(uv::Async*)#1}>::_M_invoke(std::_Any_data const&, uv::Async*&&)’���:
EventLoop.cpp:(.text+0x85):对‘uv_stop’未定义的引用
/home/aoa/Downloads/uv-cpp-master/build/libuv_cpp.a(EventLoop.cpp.o):在���数‘uv::EventLoop::GetErrorMessage(int)’中:
EventLoop.cpp:(.text+0x476):对‘uv_strerror’��定义的引用
……………………………………………………………………………………
collect2: error: ld returned 1 exit status
我看文档里的 TimerWheel 类,说是超时剔除机制,现在有个疑问,就是新连接对象被保存在两个地方了,一个是TcpServer类的connnections_成员中(connnections_中的保存要在客户端主动断开才会被删除),一个是TimerWheel类的wheel_成员中(在指定的超时时间后被删除),超时剔除机制是什么意思呢?是在指定的超时时间后,断开与客户端的连接吗,还是有其它的含义呢?
https://github.com/wlgq2/uv-cpp/blob/master/uv/TcpClient.cpp
update方法存在内存泄露
uv_tcp_t的对象new出来之后,没有对应的delete代码。
socket_ = new uv_tcp_t();
服务端同时开启多个端口,客户端同时连接这些端口
server同时开启多个端口(不同端口处理不同的数据信息,如echo,返回当前时间等等)
client同时连接这些端口发送数据
这样并发处理时会不会产生问题,主要是线程安全和崩溃问题?有没有例子可供参考,谢谢了.
是否支持openssl,或其他ssl模块
大佬,如果libuv升级到新版本支持吗
void uv::TcpServer::onAccept(EventLoop * loop, UVTcpPtr client)
{
string key;
SocketAddr::AddrToStr(client.get(), key, ipv_);
uv::LogWriter::Instance()->debug("new connect " + key);
shared_ptr<TcpConnection> connection(new TcpConnection(loop, key, client));
if (connection)
{
connection->setMessageCallback(std::bind(&TcpServer::onMessage, this, placeholders::_1, placeholders::_2, placeholders::_3));
connection->setConnectCloseCallback(std::bind(&TcpServer::closeConnection, this, placeholders::_1));
addConnnection(key, connection);
if (timerWheel_.getTimeout() > 0)
{
auto wrapper = std::make_shared<ConnectionWrapper>(connection);
connection->setWrapper(wrapper);
timerWheel_.insert(wrapper);
}
if (onNewConnectCallback_)
onNewConnectCallback_(connection);
}
else
{
uv::LogWriter::Instance()->error("create connection fail. :" + key);
}
}
新连接过来后,会将对应连接插入 std::vector<std::set<std::shared_ptr>> wheel_;
回调过程中会周期的增加index_
template
inline void TimerWheel::wheelCallback()
{
if (!timeoutSec_)
return;
if (++index_ == timeoutSec_)
{
index_ = 0;
}
wheel_[index_].clear();
}
}
若有多个用户情况下,必然会有多个连接公用一共index_,clear过程是否会导致删除多个连接的可能性。
刚刚发现一个小问题,客户端和服务端频繁相互发送数据时,TcpClient断开后,TcpConnection被销毁,但是在被销毁之前,在非事件循环线程中通过调用TcpConnection::writeInLoop向事件循环投递一块要发送的数据,由于不在事件循环中,所以这个待发送数据被放入了EventLoop类对象的待发送队列中(async_数据成员):
但是当这个发送数据的请求被执行时,TcpConnection连接对象已经被销毁,所以在写入数据时会崩溃,问题代码应该在这里:
这里将this指针作为lambda表达式的捕获参数,当TcpConnnection对象被释放了之后,this指针指向被释放的内存,所以会造成崩溃,我尝试改成如下方式,用TcpConnection的弱引用来代替this指针,在lambda表达式内部
检测TcpConnection连接对象是否有效:
EventLoop::~EventLoop()
{
if (loop_ != uv_default_loop())
{
uv_loop_close(loop_);
delete loop_;
delete async_;
}
}
如果loop不为全局静态的也要释放 async_吧
startClients(loop,serverAddr,clients,10000000);
我在用protobuf作为数据作为发送的有效数据时,发包大小和收包大小是一样的,但是protobuf解析时总是解析失败,后来我跟踪uv::Packet::readFromBuffer的解包流程,发现 uv::Packet::readFromBuffer 在返回解包后的数据时,好像把包头的内容和包尾的内容也包括在内了,后来我处理了一下,就可以解析了,这应该是一个bug吧,具体解决方法是增加对data变量的包头清除和尾的清除
// 解析有效数据包的长度 UnpackNum((uint8_t*)data.c_str() + 1, dataSize); uint16_t msgsize = dataSize + PacketMinSize(); //包不完整 if (size < msgsize) { return -1; } // 去掉包头读取的3字节 data.clear(); packetbuf->clearBufferN(sizeof(dataSize)+1); packetbuf->readBufferN(data, dataSize +1); //检查包尾 if ((uint8_t)data.back() == EndByte) { // 去掉包尾的1字节 data.pop_back(); packetbuf->clearBufferN(dataSize +1); break; }
TcpServer如何退出事件循环并做好收尾工作呢?
关于TcpConnection::onMessageReceive可读消息回调, 在处理nread < 0 时.对返回值UV_EOF采取的uv_shutdown方式关闭, 为什么不直接用uv_close呢
int TcpConnection::write(const char* buf, ssize_t size, AfterWriteCallback callback) { int rst; if (connected_) { WriteReq* req = new WriteReq; req->buf = uv_buf_init(const_cast<char*>(buf), static_cast<unsigned int>(size)); req->callback = callback; auto ptr = handle_.get(); rst = ::uv_write((uv_write_t*)req, (uv_stream_t*)ptr, &req->buf, 1, [](uv_write_t *req, int status) { WriteReq *wr = (WriteReq*)req; if (nullptr != wr->callback) { struct WriteInfo info; info.buf = const_cast<char*>(wr->buf.base); info.size = wr->buf.len; info.status = status; wr->callback(info); } delete wr; }); if (0 != rst) { uv::LogWriter::Instance()->error(std::string("write data error:"+std::to_string(rst))); if (nullptr != callback) { struct WriteInfo info = { rst,const_cast<char*>(buf),static_cast<unsigned long>(size) }; callback(info); } } } else { rst = -1; if (nullptr != callback) { struct WriteInfo info = { WriteInfo::Disconnected,const_cast<char*>(buf),static_cast<unsigned long>(size) }; callback(info); } } return rst; }
上面这段代码中,new了一个 WriteReq 对象 req,如果程序不执行到 delete wr; 语句,那不就有内存泄露呀
看了一下example的,一般是两个线程的例子,如何使用更多线程,可以考虑加EventLoop更多线程的例子么
string name;
SocketAddr::AddrToStr(socket_,name,ipv);
connection_ = make_shared<TcpConnection>(loop_, name, socket_);
常见做法是用自增数。
工程文件或Make文件都没有?
是完整可编译的工程吗?
大佬,async 能写个对应的例子吗?
for (int i = 0; i <= size; i++)
{
data[i + Packet::PacketMinSize()-1] = buffer_.front();
buffer_.pop_front();
}
如上代码需要改为:
for (int i = 0; i <= size + 4; i++)
{
data[i + 3] = buffer_.front();
buffer_.pop_front();
}
在centos7.5下使用uv-cpp, 启动echo_server, 在绑定当前服务器的公网IP时, bind失败, 返回(-99)错误: socket_bind(): unable to bind address [99]. (保证IP,端口无错误), 另外启的一个服务器使用相同的IP,端口可正常绑定.是否是libuv在绑定地址端口的时候只能填写(127.0.0.0.1或0.0.0.0). echo_server在更改IP为0.0.0.0后, 可以正常运行.
我用VS2015编译uv_cpp为静态库后,在新工程中包含include头文件目录,编译时出现如下错误:
\vs2015\vc\include\initializer_list(15): error C2894: templates cannot be declared to have 'C' lin
\vs2015\vc\include\initializer_list(59): error C2894: templates cannot be declared to have 'C' lin
\vs2015\vc\include\initializer_list(66): error C2894: templates cannot be declared to have 'C' lin
\vs2015\vc\include\xtr1common(20): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(44): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(48): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(55): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(61): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(68): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(76): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(84): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(91): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(98): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(104): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(110): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(117): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(123): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(130): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(138): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(144): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(150): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(156): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(162): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(169): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(176): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(182): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(188): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(194): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(200): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(206): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(212): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(218): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(224): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(230): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(237): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(244): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(249): error C2894: templates cannot be declared to have 'C' linkage
\vs2015\vc\include\xtr1common(255): error C2894: templates cannot be declared to have 'C' linkage
不包含uv_cpp的include文件夹时编译没有问题,百思不得其解
Program received signal SIGSEGV, Segmentation fault.
malloc_consolidate (av=av@entry=0x7ffff6f8c760 <main_arena>) at malloc.c:4147
4147 nextsize = chunksize(nextchunk);
(gdb) bt
#0 malloc_consolidate (av=av@entry=0x7ffff6f8c760 <main_arena>) at malloc.c:4147
#1 0x00007ffff6c4620e in _int_free (av=0x7ffff6f8c760 <main_arena>, p=0x7a92e0, have_lock=0) at malloc.c:4053
#2 0x00000000004e23fa in _M_dispose (__a=..., this=) at /opt/rh/devtoolset-8/root/usr/include/c++/8/ext/atomicity.h:82
#3 _M_dispose (__a=..., this=) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/basic_string.h:3250
#4 ~basic_string (this=0x7ba410, __in_chrg=) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/basic_string.h:3640
#5 uv::TcpConnection::~TcpConnection (this=0x7ba3d0, __in_chrg=) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/uv-cpp1.5.4/uv/TcpConnection.cpp:44
#6 0x00000000004e1b3a in _M_release (this=0x7ba3c0) at /opt/rh/devtoolset-8/root/usr/include/c++/8/ext/atomicity.h:69
#7 _M_release (this=0x7ba3c0) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:148
#8 ~__shared_count (this=, __in_chrg=) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:728
#9 ~__shared_ptr (this=, __in_chrg=) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:1167
#10 operator= (__r=, this=0x7a8920) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:1263
#11 operator= (__r=, this=0x7a8920) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr.h:335
#12 uv::TcpClient::onConnect(bool) () at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/uv-cpp1.5.4/uv/TcpClient.cpp:112
#13 0x00000000004e1c0a in operator() (__closure=0x0, req=, status=) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/uv-cpp1.5.4/uv/TcpClient.cpp:101
#14 uv::TcpClient::connect(uv::SocketAddr&)::{lambda(uv_connect_s*, int)#1}::_FUN(uv_connect_s*, int) () at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/uv-cpp1.5.4/uv/TcpClient.cpp:102
#15 0x00000000004f6d0a in uv__stream_connect (stream=0x7baf00) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/libuv-1.42.0/src/unix/stream.c:1391
#16 0x00000000004f6a48 in uv__stream_io (loop=0x7a7010, w=0x7baf88, events=4) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/libuv-1.42.0/src/unix/stream.c:1308
#17 0x0000000000500009 in uv__io_poll (loop=0x7a7010, timeout=312) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/libuv-1.42.0/src/unix/epoll.c:374
#18 0x00000000004ec791 in uv_run (loop=0x7a7010, mode=UV_RUN_DEFAULT) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/libuv-1.42.0/src/unix/core.c:389
#19 0x00000000004df8f0 in uv::EventLoop::run (this=0x7a76b0) at /mnt/hgfs/workspace/gitee/metel_sdp/client/third_party/uv-cpp1.5.4/uv/EventLoop.cpp:67
#20 0x0000000000448218 in main (argc=1, argv=0x7fffffffe628) at /mnt/hgfs/workspace/gitee/metel_sdp/client/sdp/app/main.cpp:101
(gdb) info thread
Id Target Id Frame
6 Thread 0x7ffff488f700 (LWP 3189688) "sdp" pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
5 Thread 0x7ffff5090700 (LWP 3189687) "sdp" pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
4 Thread 0x7ffff5891700 (LWP 3189686) "sdp" pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
3 Thread 0x7ffff6092700 (LWP 3189685) "sdp" pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
2 Thread 0x7ffff6893700 (LWP 3189682) "sdp" pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:238
请问, uv-pp在TCP服务器下, 怎么开启多线程模式呢?
new EventLoop,再delete,VS报告内存泄露
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.