我是libevent和套接字编程的新手,这就是为什么我对libevent如何作为异步和非阻塞工作有疑问。这是参考代码。https://github.com/libevent/libevent/blob/master/sample/http-server.c
static void dump_request_cb(struct evhttp_request *req, void *arg)
{
const char *cmdtype;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf;
printf("Request Startn");
sleep(30); // delay to read request to check non blocking event.
switch (evhttp_request_get_command(req)) {
case EVHTTP_REQ_GET: cmdtype = "GET"; break;
case EVHTTP_REQ_POST: cmdtype = "POST"; break;
case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
default: cmdtype = "unknown"; break;
}
printf("Received a %s request for %snHeaders:n",
cmdtype, evhttp_request_get_uri(req));
headers = evhttp_request_get_input_headers(req);
for (header = headers->tqh_first; header;
header = header->next.tqe_next) {
printf(" %s: %sn", header->key, header->value);
}
buf = evhttp_request_get_input_buffer(req);
puts("Input data: <<<");
while (evbuffer_get_length(buf)) {
int n;
char cbuf[128];
n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
if (n > 0)
(void) fwrite(cbuf, 1, n, stdout);
}
puts(">>>");
evhttp_send_reply(req, 200, "OK", NULL);
}
我在上述请求中创建了30秒的延迟。
当我从浏览器发送两个请求时。代码应该立即开始一次提供两个请求。但这并没有发生。实际情况是,第二个请求在第一个请求完成后服务,延迟30秒。这意味着为两个请求提供服务总共需要60秒。
有人能告诉我它是如何作为非阻塞工作的吗。
sleep(30)
您所做的调用是阻塞,libevent不会使用任何黑魔法来阻止您执行阻塞调用
您需要小心,并且只使用非阻塞API。在这种情况下,您希望将响应延迟30秒,因此可以很容易地使用libevent的evtimer_add()
。但这一原则也适用于您想要使用的任何类型的api,您必须以非阻塞的方式使用它们(文件读取、对其他服务器的调用、数据库访问等)。
感谢您的友好建议。
我使用线程概念实现了无阻塞套接字,并按照以下方式并行化事件。
void *newThread(void *arg){
printf("Before thread startn");
struct evhttp_request *req;
req = (struct evhttp_request *)arg;
sleep(30);
evhttp_send_reply(req, 200, "OK", NULL);
printf("After thread endn");
}
static void dump_request_cb(struct evhttp_request *req, void *arg)
{
const char *cmdtype;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf;
printf("Request Startn");
sleep(30); // delay to read request to check non blocking event.
switch (evhttp_request_get_command(req)) {
case EVHTTP_REQ_GET: cmdtype = "GET"; break;
case EVHTTP_REQ_POST: cmdtype = "POST"; break;
case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
default: cmdtype = "unknown"; break;
}
printf("Received a %s request for %snHeaders:n",
cmdtype, evhttp_request_get_uri(req));
headers = evhttp_request_get_input_headers(req);
for (header = headers->tqh_first; header;
header = header->next.tqe_next) {
printf(" %s: %sn", header->key, header->value);
}
buf = evhttp_request_get_input_buffer(req);
puts("Input data: <<<");
while (evbuffer_get_length(buf)) {
int n;
char cbuf[128];
n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
if (n > 0)
(void) fwrite(cbuf, 1, n, stdout);
}
puts(">>>");
}
这样,即使存在睡眠延迟,来自客户端的每个请求都会与以前的请求并行。我在libevent模块中找不到任何解决方案,并使用替代线程概念完成了任务。