基于C++/libuv的TCP进程间通信问题:on_read函数未触发
问题:libuv TCP服务器on_read回调未触发,客户端消息已发送
我实现了基于libuv的客户端-服务器TCP通信程序,服务器后台运行后,客户端能成功建立TCP连接并发送消息(Wireshark已确认数据包已发出),但服务器的on_read函数始终未被调用,无法在屏幕上打印客户端发送的消息。
服务器代码
#include <uv.h> #include <iostream> void on_read(uv_stream_t* client, ssize_t nread, const uv_buf_t* buf) { std::cout << "ANY DATA?\n"; if(nread > 0) { std::cout << "Received: " << std::string(buf->base, nread) << std::endl; } else if(nread < 0) { uv_close((uv_handle_t*)client, NULL); } free(buf->base); } void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { buf->base = (char*)malloc(suggested_size); buf->len = suggested_size; } void on_new_connection(uv_stream_t* server, int status) { if(status < 0) { std::cerr << "Error on_new_connection: " << uv_strerror(status) << std::endl; return; } uv_tcp_t* client = new uv_tcp_t(); uv_tcp_init(uv_default_loop(), client); if(uv_accept(server, (uv_stream_t*)client) < 0) { uv_close((uv_handle_t*)client, NULL); return; } std::cout << "New connection accepted." << std::endl; uv_read_start((uv_stream_t*)&client, alloc_buffer, on_read); } int main() { uv_tcp_t server; uv_tcp_init(uv_default_loop(), &server); struct sockaddr_in bind_addr; uv_ip4_addr("0.0.0.0", 7000, &bind_addr); if(int r = uv_tcp_bind(&server, (const struct sockaddr*)&bind_addr, 0); r < 0) { std::cerr << "Error binding server: " << uv_strerror(r) << std::endl; return 1; } if(int r = uv_listen((uv_stream_t*)&server, 128, on_new_connection); r < 0) { std::cerr << "Error starting server: " << uv_strerror(r) << std::endl; return 1; } std::cout << "Server started on port 7000." << std::endl; uv_run(uv_default_loop(), UV_RUN_DEFAULT); return 0; }
客户端代码
#include <uv.h> #include <iostream> void after_send(uv_write_t *req, int status) { std::cout << status << "as\n"; } void on_connect(uv_connect_t* req, int status) { if(status < 0) { std::cerr << "Error on_connect: " << uv_strerror(status) << std::endl; return; } std::cout << "Connected to server." << std::endl; Sleep(1000); uv_buf_t buf = uv_buf_init("Hello, server!\r\n", 14); uv_write_t write_req; uv_write(&write_req, req->handle, &buf, 1, after_send); } int main() { uv_tcp_t client; uv_tcp_init(uv_default_loop(), &client); struct sockaddr_in serv_addr; uv_ip4_addr("127.0.0.1", 7000, &serv_addr); uv_connect_t connect_req; uv_tcp_connect(&connect_req, &client, (const struct sockaddr*)&serv_addr, on_connect); return uv_run(uv_default_loop(), UV_RUN_DEFAULT); }
问题分析与修复
核心问题
服务器on_new_connection函数中,uv_read_start的参数传递错误:
// 错误写法:传递了指针的地址,类型不匹配 uv_read_start((uv_stream_t*)&client, alloc_buffer, on_read);
这里client是uv_tcp_t*类型的指针,错误地取了它的地址(&client)并转换为uv_stream_t*,导致libuv无法正确识别这个TCP客户端句柄,因此不会触发读回调。
修复代码
将uv_read_start的调用改为直接传递client指针(uv_tcp_t继承自uv_stream_t,可以直接转换):
// 正确写法:传递客户端句柄指针 uv_read_start((uv_stream_t*)client, alloc_buffer, on_read);
额外优化建议
- 内存泄漏修复:服务器中用
new创建的uv_tcp_t* client需要在连接关闭时释放,避免内存泄漏。修改on_read的关闭分支:
else if(nread < 0) { uv_close((uv_handle_t*)client, [](uv_handle_t* handle) { delete (uv_tcp_t*)handle; }); }
- 跨平台兼容性:客户端中的
Sleep(1000)是Windows特有的API,建议替换为libuv的跨平台函数uv_sleep(1000)。
内容的提问来源于stack exchange,提问作者Matthew
相关产品推荐
相关产品推荐

