编译libevent源代码(Windows)
学习笔记,只是记录本次成功用libevent源代码进行编译。环境为MinGW+VS2008+Msys。
0.下载libevent库
http://libevent.org/ 下载stable稳定版的库。
1.编译
一开始我用MinGW进行编译的,但是总是出现问题。后来参考了这个博客:http://m.blog.csdn.net/blog/bojie5744/39698599 ,把vs的运行环境包含进来,然后再进行编译
call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
./configure ; make ; make install;
如果不install也可以,libevent头文件在include里面,而生成的库在.libs里面,由于使用的是vs的运行环境。所以libevent源代码编译后的库后缀为lib,而非以前的a文件。复制 libevent.lib;libevent_core.lib;libevent_extra.lib;(最后给出我编译后的文件,方便没有vs编译环境的人下载使用。) 如果为了以后方便,可以把include目录里文件复制到开发环境的include里面,而.libs里面的三个文件也可以拷贝到mingw的lib文件夹里面。
2.libevent测试代码
#include <winsock2.h>
#include <event2/event.h>
#include <event2/event_struct.h> int main(int argc, char **argv)
{
event timeout;
return ();
}
编译选项为
g++ test.cpp -Iinclude -L. -levent -lws2_32
注意测试的编译还是不通过的。要把libevent.lib 文件名改为event.lib就可以通过了,具体为什么就还不清楚。至于为什么MS系的lib库和mingw的的a库文件有什么区别,在Windows下mingw高级版本,两者是没有区别的,都是可以调用使用的。
3.libevent自带的http服务器源码(在sample中的http-server.c)
/*
A trivial static http webserver using Libevent's evhttp. This is not the best code in the world, and it does some fairly stupid stuff
that you would never want to do in a production webserver. Caveat hackor! */ /* Compatibility for possible missing IPv6 declarations */
#include "../util-internal.h" #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <sys/types.h>
#include <sys/stat.h> #ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#ifndef S_ISDIR
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
#endif
#else
#include <sys/stat.h>
#include <sys/socket.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#endif #include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/keyvalq_struct.h> #ifdef EVENT__HAVE_NETINET_IN_H
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
# include <arpa/inet.h>
# endif
#endif #ifdef _WIN32
#ifndef stat
#define stat _stat
#endif
#ifndef fstat
#define fstat _fstat
#endif
#ifndef open
#define open _open
#endif
#ifndef close
#define close _close
#endif
#ifndef O_RDONLY
#define O_RDONLY _O_RDONLY
#endif
#endif char uri_root[]; static const struct table_entry {
const char *extension;
const char *content_type;
} content_type_table[] = {
{ "txt", "text/plain" },
{ "c", "text/plain" },
{ "h", "text/plain" },
{ "html", "text/html" },
{ "htm", "text/htm" },
{ "css", "text/css" },
{ "gif", "image/gif" },
{ "jpg", "image/jpeg" },
{ "jpeg", "image/jpeg" },
{ "png", "image/png" },
{ "pdf", "application/pdf" },
{ "ps", "application/postsript" },
{ NULL, NULL },
}; /* Try to guess a good content-type for 'path' */
static const char *
guess_content_type(const char *path)
{
const char *last_period, *extension;
const struct table_entry *ent;
last_period = strrchr(path, '.');
if (!last_period || strchr(last_period, '/'))
goto not_found; /* no exension */
extension = last_period + ;
for (ent = &content_type_table[]; ent->extension; ++ent) {
if (!evutil_ascii_strcasecmp(ent->extension, extension))
return ent->content_type;
} not_found:
return "application/misc";
} /* Callback used for the /dump URI, and for every non-GET request:
* dumps all information to stdout and gives back a trivial 200 ok */
static void
dump_request_cb(struct evhttp_request *req, void *arg)
{
const char *cmdtype;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf; 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 %s\nHeaders:\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: %s\n", header->key, header->value);
} buf = evhttp_request_get_input_buffer(req);
puts("Input data: <<<");
while (evbuffer_get_length(buf)) {
int n;
char cbuf[];
n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
if (n > )
(void) fwrite(cbuf, , n, stdout);
}
puts(">>>"); evhttp_send_reply(req, , "OK", NULL);
} /* This callback gets invoked when we get any http request that doesn't match
* any other callback. Like any evhttp server callback, it has a simple job:
* it must eventually call evhttp_send_error() or evhttp_send_reply().
*/
static void
send_document_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb = NULL;
const char *docroot = arg;
const char *uri = evhttp_request_get_uri(req);
struct evhttp_uri *decoded = NULL;
const char *path;
char *decoded_path;
char *whole_path = NULL;
size_t len;
int fd = -;
struct stat st; if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) {
dump_request_cb(req, arg);
return;
} printf("Got a GET request for <%s>\n", uri); /* Decode the URI */
decoded = evhttp_uri_parse(uri);
if (!decoded) {
printf("It's not a good URI. Sending BADREQUEST\n");
evhttp_send_error(req, HTTP_BADREQUEST, );
return;
} /* Let's see what path the user asked for. */
path = evhttp_uri_get_path(decoded);
if (!path) path = "/"; /* We need to decode it, to see what path the user really wanted. */
decoded_path = evhttp_uridecode(path, , NULL);
if (decoded_path == NULL)
goto err;
/* Don't allow any ".."s in the path, to avoid exposing stuff outside
* of the docroot. This test is both overzealous and underzealous:
* it forbids aceptable paths like "/this/one..here", but it doesn't
* do anything to prevent symlink following." */
if (strstr(decoded_path, ".."))
goto err; len = strlen(decoded_path)+strlen(docroot)+;
if (!(whole_path = malloc(len))) {
perror("malloc");
goto err;
}
evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path); if (stat(whole_path, &st)<) {
goto err;
} /* This holds the content we're sending. */
evb = evbuffer_new(); if (S_ISDIR(st.st_mode)) {
/* If it's a directory, read the comments and make a little
* index page */
#ifdef _WIN32
HANDLE d;
WIN32_FIND_DATAA ent;
char *pattern;
size_t dirlen;
#else
DIR *d;
struct dirent *ent;
#endif
const char *trailing_slash = ""; if (!strlen(path) || path[strlen(path)-] != '/')
trailing_slash = "/"; #ifdef _WIN32
dirlen = strlen(whole_path);
pattern = malloc(dirlen+);
memcpy(pattern, whole_path, dirlen);
pattern[dirlen] = '\\';
pattern[dirlen+] = '*';
pattern[dirlen+] = '\0';
d = FindFirstFileA(pattern, &ent);
free(pattern);
if (d == INVALID_HANDLE_VALUE)
goto err;
#else
if (!(d = opendir(whole_path)))
goto err;
#endif evbuffer_add_printf(evb,
"<!DOCTYPE html>\n"
"<html>\n <head>\n"
" <meta charset='utf-8'>\n"
" <title>%s</title>\n"
" <base href='%s%s'>\n"
" </head>\n"
" <body>\n"
" <h1>%s</h1>\n"
" <ul>\n",
decoded_path, /* XXX html-escape this. */
path, /* XXX html-escape this? */
trailing_slash,
decoded_path /* XXX html-escape this */);
#ifdef _WIN32
do {
const char *name = ent.cFileName;
#else
while ((ent = readdir(d))) {
const char *name = ent->d_name;
#endif
evbuffer_add_printf(evb,
" <li><a href=\"%s\">%s</a>\n",
name, name);/* XXX escape this */
#ifdef _WIN32
} while (FindNextFileA(d, &ent));
#else
}
#endif
evbuffer_add_printf(evb, "</ul></body></html>\n");
#ifdef _WIN32
FindClose(d);
#else
closedir(d);
#endif
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", "text/html");
} else {
/* Otherwise it's a file; add it to the buffer to get
* sent via sendfile */
const char *type = guess_content_type(decoded_path);
if ((fd = open(whole_path, O_RDONLY)) < ) {
perror("open");
goto err;
} if (fstat(fd, &st)<) {
/* Make sure the length still matches, now that we
* opened the file :/ */
perror("fstat");
goto err;
}
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", type);
evbuffer_add_file(evb, fd, , st.st_size);
} evhttp_send_reply(req, , "OK", evb);
goto done;
err:
evhttp_send_error(req, , "Document was not found");
if (fd>=)
close(fd);
done:
if (decoded)
evhttp_uri_free(decoded);
if (decoded_path)
free(decoded_path);
if (whole_path)
free(whole_path);
if (evb)
evbuffer_free(evb);
} static void
syntax(void)
{
fprintf(stdout, "Syntax: http-server <docroot>\n");
} int
main(int argc, char **argv)
{
struct event_base *base;
struct evhttp *http;
struct evhttp_bound_socket *handle; unsigned short port = ;
#ifdef _WIN32
WSADATA WSAData;
WSAStartup(0x101, &WSAData);
#else
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return ();
#endif
if (argc < ) {
syntax();
return ;
} base = event_base_new();
if (!base) {
fprintf(stderr, "Couldn't create an event_base: exiting\n");
return ;
} /* Create a new evhttp object to handle requests. */
http = evhttp_new(base);
if (!http) {
fprintf(stderr, "couldn't create evhttp. Exiting.\n");
return ;
} /* The /dump URI will dump all requests to stdout and say 200 ok. */
evhttp_set_cb(http, "/dump", dump_request_cb, NULL); /* We want to accept arbitrary requests, so we need to set a "generic"
* cb. We can also add callbacks for specific paths. */
evhttp_set_gencb(http, send_document_cb, argv[]); /* Now we tell the evhttp what port to listen on */
handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", port);
if (!handle) {
fprintf(stderr, "couldn't bind to port %d. Exiting.\n",
(int)port);
return ;
} {
/* Extract and display the address we're listening on. */
struct sockaddr_storage ss;
evutil_socket_t fd;
ev_socklen_t socklen = sizeof(ss);
char addrbuf[];
void *inaddr;
const char *addr;
int got_port = -;
fd = evhttp_bound_socket_get_fd(handle);
memset(&ss, , sizeof(ss));
if (getsockname(fd, (struct sockaddr *)&ss, &socklen)) {
perror("getsockname() failed");
return ;
}
if (ss.ss_family == AF_INET) {
got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port);
inaddr = &((struct sockaddr_in*)&ss)->sin_addr;
} else if (ss.ss_family == AF_INET6) {
got_port = ntohs(((struct sockaddr_in6*)&ss)->sin6_port);
inaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
} else {
fprintf(stderr, "Weird address family %d\n",
ss.ss_family);
return ;
}
addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf,
sizeof(addrbuf));
if (addr) {
printf("Listening on %s:%d\n", addr, got_port);
evutil_snprintf(uri_root, sizeof(uri_root),
"http://%s:%d",addr,got_port);
} else {
fprintf(stderr, "evutil_inet_ntop failed\n");
return ;
}
} event_base_dispatch(base); return ;
}
g++ http-server.c -Iinclude -L. -levent -lws2_32

这样就可以当作服务器了。
libevent编译后的库下载地址: http://files.cnblogs.com/files/wunaozai/libevent.zip
本文地址: http://www.cnblogs.com/wunaozai/p/4550084.html
编译libevent源代码(Windows)的更多相关文章
- Ubuntu18.10 编译libevent出现错误: creating symbolic link XXXXXX : Operation not supported
今天在VirtualBox虚拟机下的Ubuntu18.10编译libevent源代码时,按照github中使用cmake方式: $ mkdir build && cd build $ ...
- Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(无数截图)
[文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Window ...
- Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(图文并茂,还有实例下载)
[文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Window ...
- windows 平台使用 VS2017 编译 libevent 源码
一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...
- windows下编译libevent(2.1.8)及使用
一:获取libevent github地址:https://github.com/libevent/libevent/releases 下载2.1.8稳定版 二:编译libevent 我是用的visu ...
- Mac OS X上尝试编译CoreCLR源代码
CoreCLR登陆GitHub之后,体验CoreCLR首当其冲的方式就是在自己的电脑上编译它,昨天分别在Windows与Linux上成功编译了CoreCLR,详见: 1)Windows上成功编译Cor ...
- eclipse下编译hadoop源代码(转)
hadoop是一个分布式存储和分布式计算的框架.在日常使用hadoop时,我们会发现hadoop不能完全满足我们的需要,我们可能需要修改hadoop的源代码并重新编译.打包. 下面将详细描述如何从sv ...
- 编译Android源代码与内核总结
这些天花了些时间自己下载了android源代码来编译,当中走了一些弯路导致耗了些时间,如今又一次梳理总结下,让有同样想法的人自己编译的时候能少走些弯路,官方指导文档在http://source.and ...
- 编译JDK源代码【转】
用Eclipse Debug,当跟踪进jdk api里时(比如javax.swing包里的类),无法查看某些local filed的值.这是因为jdk里的代码在打包时删除了一些用于调试的信息,以减小安 ...
随机推荐
- mysql匹配模式
“_”:匹配任何单个字符“%”:匹配任意数目字符(包括零字符)“[abc]”:匹配“a”.“b”或“c”.为了命名字符的范围,使用一个“-”.“[a-z]”:匹配任何字母“[0-9]”:匹配任何数字“ ...
- 创建第一个servlet程序--HelloServlet
这篇文章是用来纪念我第一次创建一个Servlet程序,步骤我会写得详细点,也可以参考一下,后续我会将SpringMVC 跟ssh的搭建分别更新(ps:不忙的话我会更新) 工具:java jdk 1.6 ...
- tomcat,很多时候,可以在服务server.xml中可以实现一些效果
一.--日志 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="log ...
- linux-env命令解析
Linux的env命令查看当前用户的环境信息 [root@linux ~]# envHOSTNAME=linux.dmtsai.tw <== 这部主机的主机名称SHELL=/bin/bash ...
- how to Use the Tampermonkey API from the Chrome console
1.Create the following script: // ==UserScript== // @name Exports some GM functions // @namespace Wh ...
- ios真机调试步骤
http://blog.csdn.net/jianxuanlu/article/details/7283059 http://www.cnblogs.com/85538649/archive/2012 ...
- 用@resource注解方式完成属性装配
注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果. 1 需要修改xml文件的以下信息. 加入下列红色部分的4行 & ...
- Tensorflow中的name_scope和variable_scope
Tensorflow是一个编程模型,几乎成为了一种编程语言(里面有变量.有操作......). Tensorflow编程分为两个阶段:构图阶段+运行时. Tensorflow构图阶段其实就是在对图进行 ...
- windbg dds、dps、dqs
dds.dps和dqs命令显示给定范围内存的内容,它们是把内存区域转储出来,并把内存中每个元素都视为一个符号对其进行解析,dds是四字节视为一个符号,dqs是每8字节视为一个符号,dps是根据当前处理 ...
- Less入门与安装(转)
快速入门 Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).函数等功能,让 CSS 更易维护.方便制作主题.扩充. Less 可以运行在 Node.浏览 ...