如何使用libuv接受多线程的tcp连接?

时间:2018-01-11 09:08:41

标签: c++ tcp libuv

我用libuv编写了一个tcp服务器的C ++圆顶。当我检查cpu性能时,我发现圆顶是单线程运行的,我如何用多线程实现它? 目前,圆顶每秒可以处理100,000+ tcp请求,它只能吃1个CPU。 代码:

#include <iostream>
#include <atomic>
#include "uv.h"
#include <thread>
#include <mutex>
#include <map>

using namespace std;

auto loop = uv_default_loop();

struct sockaddr_in addr;

typedef struct {
    uv_write_t req;
    uv_buf_t buf;
} write_req_t;

typedef struct {
    uv_stream_t* client;
    uv_alloc_cb alloc_cb;
    uv_read_cb read_cb;
} begin_read_req;

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 free_write_req(uv_write_t *req) {
    write_req_t *wr = (write_req_t*)req;
    free(wr->buf.base);
    free(wr);
}

void echo_write(uv_write_t *req, int status) {
    if (status) {
        fprintf(stderr, "Write error %s\n", uv_strerror(status));
    }

    free_write_req(req);
}

void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
    if (nread > 0) {
        auto req = (write_req_t*)malloc(sizeof(write_req_t));

        auto *aaa = (char*)malloc(5);
        aaa[0] = '+';
        aaa[1] = 'O';
        aaa[2] = 'K';
        aaa[3] = '\r';
        aaa[4] = '\n';
        req->buf = uv_buf_init(aaa, 5);
        uv_write((uv_write_t*)req, client, &req->buf, 1, echo_write);
    }
    if (nread < 0) {
        if (nread != UV_EOF)
            fprintf(stderr, "Read error %s\n", uv_err_name(static_cast<unsigned int>(nread)));
        uv_close((uv_handle_t*)client, nullptr);
    }

    free(buf->base);
}

void acceptClientRead(uv_work_t *req) {
    begin_read_req *data = (begin_read_req *)req->data;
    uv_read_start(data->client, data->alloc_cb, data->read_cb);
}


void on_new_connection(uv_stream_t *server, int status) {
    if (status < 0) {
        cout << "New connection error:" << uv_strerror(status);
        return;
    }
    uv_tcp_t *client = (uv_tcp_t *)malloc(sizeof(uv_tcp_t));
        uv_tcp_init(loop, client);
    uv_work_t *req = (uv_work_t *)malloc(sizeof(uv_work_t));
    begin_read_req *read_req = (begin_read_req *)malloc(sizeof(begin_read_req));
    read_req->client = (uv_stream_t *)client;
    read_req->read_cb = echo_read;
    read_req->alloc_cb = alloc_buffer;
    req->data = read_req;
    if (uv_accept(server, (uv_stream_t *)client) == 0) {
        uv_read_start((uv_stream_t *)client, alloc_buffer, echo_read);
        //        uv_queue_work(workloop[0], req, acceptClientRead, nullptr);
    }
    else {
        uv_close((uv_handle_t *)client, nullptr);
    }
}

void timer_callback(uv_timer_t* handle) {
    cout << std::this_thread::get_id() << "---------" << "hello" << endl;
}

int main() {

    uv_tcp_t server{};

    uv_tcp_init(loop, &server);
    uv_ip4_addr("0.0.0.0", 8790, &addr);

    uv_tcp_bind(&server, (const struct sockaddr *) &addr, 0);

    uv_listen((uv_stream_t *)&server, 511, on_new_connection);

    uv_run(loop, UV_RUN_DEFAULT);
    return 0;
}

当然,我可以在方法“echo_read”中使写入步骤异步,但是在写入之前我没有做任何事情,我可以用另一种方式制作演示多线程以提高吞吐量吗?

0 个答案:

没有答案