Closed alongL closed 2 years ago
改成这样在windows下运行没有问题。 就是几个线程同时监听同一个地址。但使用不同的acl::server_socket对象。
#include <acl-lib/acl_cpp/lib_acl.hpp>
#include <acl-lib/fiber/libfiber.hpp>
#include <acl-lib/acl/stdlib/acl_sys_patch.h>
// 客户端协程处理类,用来回显客户发送的内容,每一个客户端连接绑定一个独立的协程
class fiber_echo : public acl::fiber
{
public:
explicit fiber_echo(acl::socket_stream* conn) : conn_(conn) {}
private:
acl::socket_stream* conn_;
~fiber_echo() override { delete conn_; }
// @override
void run() override {
char buf[8192];
while (true) {
int ret = conn_->read(buf, sizeof(buf), false);
if (ret == -1) {
break;
}
if (conn_->write(buf, ret) != ret) {
break;
}
}
delete this; // 自销毁动态创建的协程对象
}
};
// 独立的协程过程,接收客户端连接,并将接收的连接与新创建的协程进行绑定
class fiber_listen : public acl::fiber
{
public:
explicit fiber_listen(acl::server_socket& listener) : listener_(listener) {}
private:
acl::server_socket& listener_;
~fiber_listen() override = default;
// @override
void run() override {
while (true) {
acl::socket_stream* conn = listener_.accept(); // 等待客户端连接
if (conn == nullptr) {
printf("accept failed: %s\r\n", acl::last_serror());
break;
}
printf("new client : %s\r\n", conn->get_peer_ip());
// 创建并启动单独的协程处理客户端连接
acl::fiber* fb = new fiber_echo(conn);
fb->start();
}
delete this;
}
};
// 独立的线程调度类
class thread_server : public acl::thread
{
public:
explicit thread_server() {
}
~thread_server() override = default;
private:
acl::server_socket listener_;
// @override
void* run() override {
const char* addr = "127.0.0.1:8000";
acl::server_socket listener;
// 监听本地地址
if (!listener.open(addr)) {
printf("listen %s error %s\r\n", addr, acl::last_serror());
return NULL;
}
// 创建并启动独立的监听协程,接受客户端连接
acl::fiber* fb = new fiber_listen(listener);
fb->start();
// 启动协程调度器
acl::fiber::schedule(); // 内部处于死循环过程
return NULL;
}
};
int main(void)
{
acl_socket_init();
std::vector<acl::thread*> threads;
// 创建多个独立的线程对象,每个线程启用独立的协程调度过程
for (int i = 0; i < 4; i++) {
acl::thread* thr = new thread_server();
threads.push_back(thr);
thr->start();
}
for (auto& thread : threads) {
thread->wait();
delete thread;
}
getchar();
return 0;
}
acl用着感觉还是不错的样子。
是的,那篇文章给出的多线程中的例子存在一些问题,因为 acl fiber 是单线程调试方式,所以同一 socket 句柄不能在多个线程中的协程中使用,应该如你上面给出的例子那样,每个线程创建一个监听对象才可以;另外,我也专门写了一个示例来展示在多线程协程下,如何通过 acl::fiber_tbox来传递连接对象的情况,该示例位置:lib_fiber\samples-c++1x\server-threads ,在该例子中,在一个独立的线程(非协程模式)中接收连接,通过每个协程模式的线程中的 fiber_tbox 将连接对象传递给相应的协程。 非常感谢你指出的错误,我将会修正文章中的错误。 --zsx
感谢回复! 那在linux下并未报错,但应该也不能这么用吧?
是的,在linux下也不该那样使用。
在linux下不会出错。 源码用的是https://blog.csdn.net/zsxxsz/article/details/89007127?spm=1001.2014.3001.5501 第四点”使用多核“ 的那个例子。
出错的位置: event_iocp.c