1

我想创建一个 c++ 网络服务器,它将为登陆我网站的每个用户执行一项任务。由于任务可能计算量很大(现在只是长时间的睡眠),我想在不同的线程上处理每个用户。我正在使用猫鼬来设置网络服务器。

不同的进程(在我的代码中只有一个,又名 server1)设置正确并且似乎运行正常。但是,线程似乎一个接一个地排队,所以如果 2 个用户到达终点,第二个用户必须等到第一个用户完成。我错过了什么?线程是否超出范围?是否有我应该使用的“线程管理器”?

#include "../../mongoose.h"
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <thread>


//what happens whenever someone lands on an endpoint
void myEvent(struct mg_connection *conn){
    //long delay...
    std::thread mythread(usleep, 2*5000000);
    mythread.join();
    mg_send_header(conn, "Content-Type", "text/plain");
    mg_printf_data(conn, "This is a reply from server instance # %s",
    (char *) conn->server_param);
}

static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
    if (ev == MG_REQUEST) {
        myEvent(conn);
        return MG_TRUE;
    } else if (ev == MG_AUTH) {
        return MG_TRUE;
    } else {
        return MG_FALSE; 
    }
}

static void *serve(void *server) {
    for (;;) mg_poll_server((struct mg_server *) server, 1000);
    return NULL;
}

int main(void) {
    struct mg_server *server1;
    server1 = mg_create_server((void *) "1", ev_handler);
    mg_set_option(server1, "listening_port", "8080");
    mg_start_thread(serve, server1);
    getchar();
    return 0;
}
4

3 回答 3

2

长时间运行的请求应该这样处理:

static void thread_func(struct mg_connection *conn) {
  sleep(60);  // simulate long processing
  conn->user_data = "done";  // Production code must not do that.
                             // Other thread must never access connection
                             // structure directly. This example is just
                             // for demonstration.
}

static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
  switch (ev) {
    case MG_REQUEST:
      conn->user_data = "doing...";
      spawn_thread(thread_func, conn);
      return MG_MORE;  // Important! Signal Mongoose we are not done yet
    case MG_POLL:
      if (conn->user_data != NULL && !strcmp(conn->user_data, "done")) {
        mg_printf(conn, "HTTP/1.0 200 OK\n\n  Done !");
        return MG_TRUE;  // Signal we're finished. Mongoose can close this connection
      }
      return MG_FALSE;  // Still not done
于 2015-04-23T15:30:58.143 回答
0

James Adkison 是绝对正确的。所以,如果代码的开头看起来像这样:

void someFunc(struct mg_connection *conn){
    usleep(2*5000000);
    std::cout << "hello!" << std::endl;
    std::cout<< "This finished from server instance #"<<conn<<std::endl;
    mg_send_header(conn, "Content-Type", "application/json");
    mg_printf_data(conn, "{\"message\": \"This is a reply from server instance # %s\"}",
    // (char *) conn->server_param); 
}
void myEvent(struct mg_connection *conn){
    std::thread mythread(someFunc,conn);
    mythread.detach();
    std::cout<< "This is a reply from server instance #"<<(char *) conn->server_param<<std::endl;   
}

static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
    if (ev == MG_REQUEST) {
        myEvent(conn);

        return MG_TRUE;
    } else if (ev == MG_AUTH) {
    //.... exactly as before
    //....

然后程序工作。基本上区别在于替换.join().detach(). someFunc 现在正在为 2 个用户并行运行——太棒了!谢谢!

于 2015-02-25T18:20:33.193 回答
0

警告:我不熟悉猫鼬

我的假设:

  • serve函数正在轮询传入连接

如果执行mg_poll_server的线程是触发调用的同一线程,ev_handler那么您的问题是ev_handler调用myEvent启动长时间运行的操作并阻塞线程(即,通过调用join)。在这种情况下,您还阻塞了处理传入连接的线程(即,后续客户端必须等待第一个客户端完成其工作),这似乎是您所描述的行为。

我不确定真正的任务应该做什么,所以我不能确定你应该如何解决这个问题。也许在您的用例中可能会调用,detach否则您可能会跟踪正在执行的线程并推迟join对它们的调用,直到服务器关闭。

于 2015-02-25T17:19:26.350 回答