前面已经介绍过了mongoose的生产者过程,现在介绍下消费者过程。mongoose默认创建了10个worker_thread()线程来处理已接受的连接。worker_thread()函数原型如下:
static void worker_thread(struct mg_context *ctx)
{
struct mg_connection *conn;
int buf_size = atoi(ctx->config[MAX_REQUEST_SIZE]);
conn = (struct mg_connection *) calloc(1, sizeof(*conn) + buf_size);
if (conn == NULL)
{
cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
return;
}
conn->buf_size = buf_size;
conn->buf = (char *) (conn + 1);
// Call consume_socket() even when ctx->stop_flag > 0, to let it signal
// sq_empty condvar to wake up the master waiting in produce_socket()
while (consume_socket(ctx, &conn->client))
{
conn->birth_time = time(NULL);
conn->ctx = ctx;
// Fill in IP, port info early so even if SSL setup below fails,
// error handler would have the corresponding info.
// Thanks to Johannes Winkelmann for the patch.
// TODO(lsm): Fix IPv6 case
conn->request_info.remote_port = ntohs(conn->client.rsa.sin.sin_port);
memcpy(&conn->request_info.remote_ip,
&conn->client.rsa.sin.sin_addr.s_addr, 4);
conn->request_info.remote_ip = ntohl(conn->request_info.remote_ip);
conn->request_info.is_ssl = conn->client.is_ssl;
if (!conn->client.is_ssl ||
(conn->client.is_ssl && sslize(conn, SSL_accept)))
{
process_new_connection(conn);
}
close_connection(conn);
}
free(conn);
// Signal master that we're done with connection and exiting
(void) pthread_mutex_lock(&ctx->mutex);
ctx->num_threads--;
(void) pthread_cond_signal(&ctx->cond);
assert(ctx->num_threads >= 0);
(void) pthread_mutex_unlock(&ctx->mutex);
DEBUG_TRACE(("exiting"));
}
先创建了一个mg_connection类型的结构体变量,然后利用该变量
从连接队列尾部取出一个连接来处理。若队列为空的话一直等待直到被告知有连接准备好被处理。取出连接后用一些变量填充改结构体,然后就进入了主题:处理新连接。mongoose调用process_new_connection()函数来处理一个新连接。该函数也是mongoose最关键的函数之一。process_new_connection流程如下:初始化变量->读取请求->解析http请求。作为一个web服务器,解析http请求当然是它的核心功能。