基于PhotonLib开发后端时TCP服务器端口绑定失败(core dumped)求助
基于PhotonLib开发后端时TCP服务器端口绑定失败(core dumped)求助
嘿,我仔细看了你的代码,立刻就找到导致端口绑定失败并core dump的原因了!
问题核心:重复绑定同一个端口
你在start()函数里启动了8个worker线程,每个线程都会进入worker_loop(),而每个worker线程都创建了一个全新的TCP Socket Server,然后尝试绑定同一个8080端口。
TCP协议的规则是:同一个端口在同一时间只能被一个Socket监听实例绑定(除非开启SO_REUSEPORT选项,但这不是常规Web服务的做法)。第一个worker线程绑定端口会成功,但后面的7个线程都会绑定失败,抛出std::runtime_error,最终导致程序core dump。
看一下你worker_loop()里的问题代码:
void HttpServer::worker_loop() { // 每个线程都新建一个server,重复绑定端口! auto server = photon::net::new_tcp_socket_server(); if (!server->bind(options_.port)) { throw std::runtime_error("Failed to bind TCP server"); } if (!server->listen()) { throw std::runtime_error("Failed to listen"); } // ... 后续accept逻辑 }
修复方案:单监听Socket + 多Worker线程处理连接
正确的做法是只创建并绑定一次监听Socket Server,然后让所有worker线程共享这个监听实例,共同处理客户端的连接请求。
步骤1:修改HttpServer类,添加监听Server成员
在server.hpp的HttpServer类定义中,添加一个共享的监听Socket Server成员:
#include <photon/net/socket.h> namespace obeng { struct ServerOptions { // 保持你的原有定义 uint16_t port = 8080; size_t num_workers = 8; size_t buffer_size = 4096; }; class HttpServer { public: // 保持原有构造、router相关方法 HttpServer(const ServerOptions& options); void set_router(std::unique_ptr<HttpRouter> router); HttpRouter& router(); void start(); private: ServerOptions options_; std::unique_ptr<HttpRouter> router_; // 添加共享的监听server成员 photon::net::ISocketServer* listen_server_ = nullptr; void worker_loop(); void handle_connection(photon::net::ISocketStream* stream); }; }
步骤2:修改start()函数,提前完成端口绑定
把创建和绑定监听Server的逻辑移到start()函数中,只执行一次,再启动worker线程:
void HttpServer::start() { if (!router_) { throw std::runtime_error("No router configured"); } photon::init(photon::INIT_EVENT_DEFAULT, photon::INIT_IO_DEFAULT); DEFER(photon::fini()); // 只创建并绑定一次监听Server listen_server_ = photon::net::new_tcp_socket_server(); if (!listen_server_) { throw std::runtime_error("Failed to create TCP socket server"); } DEFER(delete listen_server_); // 绑定端口(仅执行一次) if (!listen_server_->bind(options_.port)) { throw std::runtime_error("Failed to bind TCP server"); } if (!listen_server_->listen()) { throw std::runtime_error("Failed to listen"); } // 启动所有worker线程,共享同一个监听server for (size_t i = 0; i < options_.num_workers; ++i) { photon::thread_create11([this]() { this->worker_loop(); }); } photon::thread_sleep(-1); }
步骤3:修改worker_loop(),共享监听Server
让每个worker线程直接使用已经绑定好的listen_server_去accept连接,不再重复创建server:
void HttpServer::worker_loop() { while (true) { // 使用共享的监听server接受连接 auto* stream = listen_server_->accept(); if (!stream) break; photon::thread_create11([this, stream]() { DEFER(delete stream); this->handle_connection(stream); }); } }
额外检查点
如果修改后还是有问题,可以做以下验证:
- 确认端口真的未被占用:在Linux下可以用
lsof -i :8080或ss -tulpn | grep 8080检查 - 确认程序有足够权限绑定8080端口(1024以下端口需要root权限,但8080是非特权端口,普通用户也能绑定)
这样修改后,你的服务器应该就能正常启动并在8080端口监听了!
内容来源于stack exchange
相关产品推荐
相关产品推荐

