使用LIBEVENT构建HTTP服务


//开启服务
void startHttpServer(int port)
{
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);

//创建监听SOCKET  启动http服务
int fd = socket(AF_INET, SOCK_STREAM, 0);
int one = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("");
log("bind error!\n");
return ;
}

if (listen(fd, 0x7fffffff) == -1) {
log("listen error!\n");
return ;
}
setnonblocking(fd);

int len = sizeof(addr);
if (getsockname(fd, (struct sockaddr *)&addr, &len) != 0) {
log("getsockname error!\n");
return ;
}

//处理http请求  可以设置多个请求防止一个阻塞。
int i;
for (i = 0; i < THR_NUM - 1; ++i) {
struct event_base *base = event_init();
struct evhttp *httpd = evhttp_new(base);
evhttp_accept_socket(httpd, fd);//将SOCKET与HTTP服务绑定。
//evhttp_set_timeout(httpd, timeout);
evhttp_set_gencb(httpd, genericHandle, NULL);//用户请求的回调接口。
                //开启线程 处理HTTP请求
HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, dispatch, base, 0, NULL); 
if( hThread1 != NULL )   
{      
CloseHandle(hThread1);   

}

struct event_base *base = event_init();
struct evhttp *httpd = evhttp_new(base);
evhttp_accept_socket(httpd, fd);
//evhttp_set_timeout(httpd, timeout);
evhttp_set_gencb(httpd, genericHandle, NULL);
event_base_dispatch(base);

}

//设置网络非阻塞。

void setnonblocking(SOCKET sock)
{
u_long ulArg = 1;
if (::ioctlsocket(sock, FIONBIO, &ulArg) == SOCKET_ERROR) {
log("ioctlsocket error\n");
}
}

//线程中只调用等待即可。
unsigned int STDCALL dispatch(void* arg)
{
event_base_dispatch((struct event_base*)arg);
return NULL;

}

//处理用户发出的请求

void 
OpenClient(struct evhttp_request* req, struct evkeyvalq* query_headers, int* response_code, struct evbuffer *response_buf)
{
const char* type = evhttp_find_header(query_headers, "type");
if (type == NULL) {
*response_code = HTTP_INTERNAL;
log("type == NULL");
return;
}

char* response_data ="{\"ret\":0}";//需要返回的信息,可以是JSON等约定类型的串。
evbuffer_add(response_buf, response_data, strlen(response_data) + 1);
free(response_data);

}

//处理接收的命令

void genericHandle(struct evhttp_request* req, void *arg)
{
const struct evhttp_uri* uri = evhttp_request_get_evhttp_uri(req);
const char* path = evhttp_uri_get_path(uri);
const char* query_str = evhttp_uri_get_query(uri);
struct evkeyvalq headers;
if (evhttp_parse_query_str(query_str, &headers) == -1) {
log("evhttp_parse_query_str error!\n");
return;
}

int response_code = HTTP_OK;
struct evbuffer *buf = evbuffer_new();
size_t post_size = EVBUFFER_LENGTH(req->input_buffer);
if (post_size > 0)//用这种方式处理POST中BODY的数据。
{
char* pcBuf = new char[post_size + 1];
memset(pcBuf,0,post_size+1);
memcpy (pcBuf, EVBUFFER_DATA(req->input_buffer), post_size);

if (strcmp(path, "/SendMessageToProcess") == 0) {//这儿解析命令
//--
} else if (strcmp(path, "/StartProcessWithParam") == 0) {
//--

else
{
return;//命令错误
}

        char* response_data = "";
evbuffer_add(buf, response_data, strlen(response_data) + 1);
free(response_data);

// char buf[1024] = {0};
// evbuffer_remove(req->input_buffer, &buf, sizeof(buf) - 1);
// event_base_loopbreak((struct event_base*)arg);
//这种数据是约定好的,可能是JSON,或纯数据,可以是大文件。
delete []pcBuf;
}
else
{
//解析HTTP请求的命令  GET?
string strTmp = path;

                //分割传入的命令。
vector<string> vecInput = split(path,"/");
if (vecInput.size() > 0)
{
if (vecInput[0] == "StartProcessWithParam")//解析命令
{
}
}
}

// No 'Access-Control-Allow-Origin' header is present on the requested resource//解决跨域调用返回的报错问题 
evhttp_add_header(evhttp_request_get_output_headers(req), "Access-Control-Allow-Origin","*"); 

evhttp_send_reply(req, response_code, "ok", buf);
evbuffer_free(buf);

}


//字符串分割函数
vector< string> split( string str, string pattern)
{
vector<string> ret;
if(pattern.empty()) return ret;
size_t start=0,index=str.find_first_of(pattern,0);
while(index!=str.npos)
{
if(start!=index)
ret.push_back(str.substr(start,index-start));
start=index+1;
index=str.find_first_of(pattern,start);
}
if(!str.substr(start).empty())
ret.push_back(str.substr(start));
return ret;

}


//使用方法:将LIBEVENT引入,在UI层开启线程调用  startHttpServer传入端口号即可。

/*

_beginthread(ThreadHttpServer,0,this);

void ThreadHttpServer( void *dummy )
{
startHttpServer(端口号);
}

*/


//网页POST格式:

/*
注意客户端须有: xhrFields: { //允许跨域访问是添加cookie
withCredentials: false
},  或者不加此项,不能为TRUE。
如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
<title>Insert title here</title>
<script type="text/javascript" src="jquery-1.8.3.js"></script>
<script type="text/javascript">
function start() {
jQuery.support.cors = true; 
$.ajax({
url : 'http://127.0.0.1:8003/SendMessageToProcess',
type : "post",
data : {  //这样传输后数据格式为 type=sdk&param=s  
type : "1",
param : "5"
},
//以下为JSON格式数据。
// data : JSON.stringify({
// type : "1",
// param : " gf"
// }),
success : function(data) {
console.log(data)
}
});
}
</script>
</head>
<body>
<button οnclick="start()">测试</button>
</body>
</html>*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
libevent是一个开源的事件驱动库,可以用来开发高并发的网络应用程序。下面是一个使用libevent实现的简单的HTTP服务器示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <event2/event.h> #include <event2/http.h> void http_cb(struct evhttp_request *req, void *arg) { const char *uri = evhttp_request_get_uri(req); printf("Request URI: %s\n", uri); struct evbuffer *evb = evbuffer_new(); if (evb == NULL) { fprintf(stderr, "Failed to create evbuffer\n"); evhttp_send_error(req, HTTP_INTERNAL, "Internal Server Error"); return; } evbuffer_add_printf(evb, "Hello World!"); evhttp_send_reply(req, HTTP_OK, "OK", evb); evbuffer_free(evb); } int main(int argc, char *argv[]) { struct event_base *base = event_base_new(); if (base == NULL) { fprintf(stderr, "Failed to create event_base: %s\n", strerror(errno)); return EXIT_FAILURE; } struct evhttp *httpd = evhttp_new(base); if (httpd == NULL) { fprintf(stderr, "Failed to create evhttp: %s\n", strerror(errno)); return EXIT_FAILURE; } if (evhttp_bind_socket(httpd, "0.0.0.0", 8080) != 0) { fprintf(stderr, "Failed to bind to 0.0.0.0:8080: %s\n", strerror(errno)); return EXIT_FAILURE; } evhttp_set_cb(httpd, "/", http_cb, NULL); printf("HTTP server started on 0.0.0.0:8080\n"); event_base_dispatch(base); evhttp_free(httpd); event_base_free(base); return EXIT_SUCCESS; } ``` 这个HTTP服务器监听本地8080端口,处理根路径的请求,返回"Hello World!"。可以使用curl命令测试: ``` $ curl http://localhost:8080/ Hello World! ``` 这只是一个简单的示例,实际的HTTP服务器需要更多的功能和处理逻辑。libevent提供了丰富的API和事件处理机制,可以很方便地实现高并发、高性能的网络应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值