/* * * @build make examples * @server bin/one-acceptor-multi-workers 1234 * @client bin/nc 127.0.0.1 1234 * nc 127.0.0.1 1234 * telnet 127.0.0.1 1234 */ #include "hv/hloop.h" #include "hv/hthread.h" #include "utils.h" #include "tcp_inbound.h" #include "udp_inbound.h" #include "spdlog/spdlog.h" #include "spdlog/async.h" #include "spdlog/sinks/stdout_color_sinks.h" static const char *host = "0.0.0.0"; static int port = 8080; static int thread_num = 4; static hloop_t *tcpaccept_loop = NULL, *udpbind_loop = NULL; static void new_conn_event(hevent_t *ev) { hloop_t *loop = ev->loop; hio_t *io = (hio_t *)hevent_userdata(ev); hio_attach(loop, io); tcp_on_accept(io, ev); } static void on_accept(hio_t *io) { hio_detach(io); hloop_t *worker_loop = get_next_loop(); hevent_t ev; memset(&ev, 0, sizeof(ev)); ev.loop = worker_loop; ev.cb = new_conn_event; ev.userdata = io; hloop_post_event(worker_loop, &ev); } static HTHREAD_RETTYPE worker_thread(void *userdata) { hloop_t *loop = (hloop_t *)userdata; hloop_run(loop); return 0; } static HTHREAD_RETTYPE tcpaccept_thread(void *userdata) { hloop_t *loop = (hloop_t *)userdata; hio_t *listenio = hloop_create_tcp_server(loop, host, port, on_accept); if (listenio == NULL) { exit(1); } int listeniofd = hio_fd(listenio); hloop_run(loop); close(listeniofd); return 0; } static HTHREAD_RETTYPE udpbind_thread(void *userdata) { hloop_t *loop = (hloop_t *)userdata; hio_t *bindio = hloop_create_udp_server(loop, host, port); if (bindio == NULL) { exit(1); } int bindfd = hio_fd(bindio); spdlog::info("ProxyServer start: udp->{}", port); hevent_set_userdata(bindio, loop); //必须 hio_setcb_read(bindio, udp_on_recvfrom); hio_setcb_write(bindio, udp_on_writed); hio_setcb_close(bindio, udp_on_close); hio_read(bindio); hloop_run(loop); close(bindfd); return 0; } int main(int argc, char **argv) { int type = 0; if (argc == 3) { type = atoi(argv[1]); port = atoi(argv[2]); } int cores = std::thread::hardware_concurrency(); if (cores > 0) { thread_num = cores; } auto console_sink = std::make_shared(); auto logger = std::make_shared("my_logger", console_sink); // 设置异步模式,设置线程数(0 表示使用 CPU 核心数) spdlog::init_thread_pool(8192, thread_num); // 设置异步日志器 spdlog::set_default_logger(std::make_shared( "ProxyServer", console_sink, spdlog::thread_pool(), spdlog::async_overflow_policy::block)); spdlog::info("ProxyServer start: threadNum:{:d}", thread_num); if (type == 1) { // Udp udpbind_loop = hloop_new(HLOOP_FLAG_AUTO_FREE); udpbind_thread(udpbind_loop); } else { // Tcp init_loop(thread_num, worker_thread); spdlog::info("ProxyServer start: tcp->{}", port); tcpaccept_loop = hloop_new(HLOOP_FLAG_AUTO_FREE); tcpaccept_thread(tcpaccept_loop); } return 0; }