在同一个套接字中使用 libevent 处理 HTTP 和 HTTPS 请求
Posted
技术标签:
【中文标题】在同一个套接字中使用 libevent 处理 HTTP 和 HTTPS 请求【英文标题】:Handling HTTP and HTTPS requests with libevent in a same socket 【发布时间】:2013-07-09 21:43:32 【问题描述】:参照https://github.com/ppelleti/https-example,我尝试定义以下代码以处理(服务器端)https 和http 请求。有没有更简单的方法来处理单个监听套接字中的 https 和 http 请求?提前致谢
static int serve_some_http (void)
struct event_base *base;
struct evhttp *https, *http;
struct evhttp_bound_socket *https_handle, *http_handle;
unsigned short port = COMMON_HTTPS_PORT;
#ifdef _WIN32
WSADATA WSAData;
WSAStartup (0x101, &WSAData);
#endif
base = event_base_new ();
if (! base)
fprintf (stderr, "Couldn't create an event_base: exiting\n");
return 1;
/* Create a new evhttp object to handle requests. */
https = evhttp_new (base);
http = evhttp_new (base);
if ((! https)||(! http))
fprintf (stderr, "couldn't create evhttp. Exiting.\n");
return 1;
SSL_CTX *ctx = SSL_CTX_new (SSLv23_server_method ());
SSL_CTX_set_options (ctx,
SSL_OP_SINGLE_DH_USE |
SSL_OP_SINGLE_ECDH_USE |
SSL_OP_NO_SSLv2);
/* Cheesily pick an elliptic curve to use with elliptic curve ciphersuites.
* We just hardcode a single curve which is reasonably decent.
* See http://www.mail-archive.com/openssl-dev@openssl.org/msg30957.html */
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
if (! ecdh)
die_most_horribly_from_openssl_error ("EC_KEY_new_by_curve_name");
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh))
die_most_horribly_from_openssl_error ("SSL_CTX_set_tmp_ecdh");
/* Find and set up our server certificate. */
const char *certificate_chain = SERVER_CERT_PEM;
const char *private_key = SERVER_PRIV_PEM;
server_setup_certs (ctx, certificate_chain, private_key);
/* This is the magic that lets evhttp use SSL. */
evhttp_set_bevcb (https, bevcb, ctx);
/* This is the callback that gets called when a request comes in. */
evhttp_set_gencb (https, https_document_cb, NULL);
evhttp_set_gencb (http, http_document_cb, NULL);
/* Now we tell the evhttp what port to listen on */
https_handle = evhttp_bind_socket_with_handle (https, "127.0.0.1", port);
http_handle = evhttp_bind_socket_with_handle (http, "127.0.0.1", port+1);
if ((! https_handle)||(! http_handle))
fprintf (stderr, "couldn't bind to port %d. Exiting.\n", (int) port);
return 1;
/* Extract and display the address we're listening on. */
sock_hop ss, sss;
evutil_socket_t fds,fd;
ev_socklen_t socklen = sizeof (ss);
ev_socklen_t s_socklen = sizeof (ss);
char addrbuf[128];
char s_addrbuf[128];
void *inaddr, *s_inaddr;
const char *addr, *s_addr;
int got_port = -1;
int s_got_port = -1;
fds = evhttp_bound_socket_get_fd (https_handle);
memset (&sss, 0, sizeof(sss));
if (getsockname (fds, &sss.sa, &s_socklen))
perror ("getsockname() failed");
return 1;
if (sss.ss.ss_family == AF_INET)
s_got_port = ntohs (sss.in.sin_port);
s_inaddr = &sss.in.sin_addr;
else if (sss.ss.ss_family == AF_INET6)
s_got_port = ntohs (sss.i6.sin6_port);
s_inaddr = &sss.i6.sin6_addr;
else
fprintf (stderr, "Weird address family %d\n", sss.ss.ss_family);
return 1;
s_addr = evutil_inet_ntop (sss.ss.ss_family, s_inaddr, s_addrbuf,
sizeof (s_addrbuf));
if (s_addr)
printf ("Listening HTTPS on %s:%d\n", s_addr, s_got_port);
else
fprintf (stderr, "evutil_inet_ntop failed\n");
return 1;
fd = evhttp_bound_socket_get_fd (http_handle);
memset (&ss, 0, sizeof(ss));
if (getsockname (fd, &ss.sa, &socklen))
perror ("getsockname() failed");
return 1;
if (ss.ss.ss_family == AF_INET)
got_port = ntohs (ss.in.sin_port);
inaddr = &ss.in.sin_addr;
else if (ss.ss.ss_family == AF_INET6)
got_port = ntohs (ss.i6.sin6_port);
inaddr = &ss.i6.sin6_addr;
else
fprintf (stderr, "Weird address family %d\n", ss.ss.ss_family);
return 1;
addr = evutil_inet_ntop (ss.ss.ss_family, inaddr, addrbuf,
sizeof (addrbuf));
if (addr)
printf ("Listening HTTP on %s:%d\n", addr, got_port);
else
fprintf (stderr, "evutil_inet_ntop failed\n");
return 1;
event_base_dispatch (base);
/* not reached; runs forever */
return 0;
【问题讨论】:
【参考方案1】:不,您不能从同一个端口提供 HTTPS 和 HTTP,并且 libevent 需要两个 struct http
实例来处理两者。
【讨论】:
以上是关于在同一个套接字中使用 libevent 处理 HTTP 和 HTTPS 请求的主要内容,如果未能解决你的问题,请参考以下文章
知道所有回调都使用 libevent 和 bufferevent_free 运行