簡單的Http Server
使用Libevent內置的http相關接口,可以很容易的構建一個Http Server,一個簡單的Http Server如下:
#include <event2/.h><event2/buffer.h><event2/http.h><Winsock2.h><stdlib.h><stdio.h> (WSAStartup(MAKEWORD(,) , &wsaData) != - generic_handler( evhttp_request *req, * evbuffer *buf =(! main( argc, * http_port = *http_addr = event_base * = evhttp * http_server = evhttp_new((! - ret =(ret!= -
通過Libevent的接口構建一個Http Server的過程如下:
(1)初始化:在event_base上新建一個evhttp,將這個evhttp綁定到監聽的IP和端口號。
(2)設置Http回調函數:使用evhttp_set_gencb設置Http Server的處理請求的回調函數。
(3)啟動Http Server:等待請求進入事件循環。
在Http Server中使用定時器提供更新服務
#include <event2/.h><event2/buffer.h><event2/http.h><sys/stat.h><Winsock2.h><assert.h><.h><stdlib.h><stdio.h> DEFAULT_FILE "F:\\Libevent\\LibeventTest\\Debug\\sample.txt" *= filename[ counter = * size = *(stat(filename,&buf)< (buf.st_mtime > (counter++*f = fopen(filename, (f ==== ( *)malloc(size+,size+(= read_file_timer_cb(evutil_socket_t listener, , * (!& load_file( event_base * = = loadfile_event = evtimer_new( evtimer_add(loadfile_event,& generic_handler( evhttp_request *req, * evbuffer *buf =(!(WSAStartup(MAKEWORD(,) , &wsaData) != - main( argc, * http_port = *http_addr = (argc > event_base * = evhttp * http_server = evhttp_new((! - ret =(ret!= -
在這個Http Server中提供了一個每5秒觸發一次的定時器,讀取一個文件,如果這個文件被更新過,則讀取更新後的內容。
當訪問這個Http Server時,提供這個文件中最新的內容。
多線程的Http Server
在上面的Http Server中,處理Http請求的回調函數generic_handler和定時器讀取文件的回調函數read_file_timer_cb都在同一個event_base的dispatch中,並且都在同一個進程中,使用多線程可以改善程序的性能,下面是一個來自網絡的多線程Http Server:
#include <.h><evhttp.h><pthread.h><errno.h><.h><fcntl.h><sys/socket.h><sys/types.h><netinet/.h> httpserver_bindsocket( port, httpserver_start( port, nthreads, * httpserver_Dispatch( * httpserver_GenericHandler( evhttp_request *req, * httpserver_ProcessRequest( evhttp_request * httpserver_bindsocket( port, = socket(AF_INET, SOCK_STREAM, (nfd < ) - one = = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, ( *)&one, (&addr, , ==== bind(nfd, ( sockaddr*)&addr, (r < ) -= (r < ) - ((flags = fcntl(nfd, F_GETFL, )) < || fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < - httpserver_start( port, nthreads, nfd = (nfd < ) - (i = ; i < nthreads; i++ event_base * = ( == NULL) - evhttp *httpd = evhttp_new( (httpd == NULL) -= (r != ) -= pthread_create(&ths[i], NULL, httpserver_Dispatch, (r != ) - (i = ; i < nthreads; i++* httpserver_Dispatch( * event_base* httpserver_GenericHandler( evhttp_request *req, * httpserver_ProcessRequest( evhttp_request * evbuffer *buf = (buf == NULL) main(, ,
上面的代碼基於Libevent 1.X版本的,不過很容易很看懂:在一個監聽socket上創建了多個event_base實例和evhttp實例,在不同的線程中調度不同的event_base,繼而可以在不同的線程中處理http請求。
這裡還有一個基於Libevent的多線程Http Server:https://sourceforge.net/projects/libevent-thread/,看源代碼處理的過程和上面類似,只是每次在監聽的socket上accept一個連接請求時,將對應的處理放到一個工作隊列裡,在隊列裡由多線程處理相應的回調函數。