学习笔记,只是记录本次成功用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)的更多相关文章

  1. Ubuntu18.10 编译libevent出现错误: creating symbolic link XXXXXX : Operation not supported

    今天在VirtualBox虚拟机下的Ubuntu18.10编译libevent源代码时,按照github中使用cmake方式: $ mkdir build && cd build $ ...

  2. Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(无数截图)

    [文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Window ...

  3. Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(图文并茂,还有实例下载)

    [文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Window ...

  4. windows 平台使用 VS2017 编译 libevent 源码

    一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...

  5. windows下编译libevent(2.1.8)及使用

    一:获取libevent github地址:https://github.com/libevent/libevent/releases 下载2.1.8稳定版 二:编译libevent 我是用的visu ...

  6. Mac OS X上尝试编译CoreCLR源代码

    CoreCLR登陆GitHub之后,体验CoreCLR首当其冲的方式就是在自己的电脑上编译它,昨天分别在Windows与Linux上成功编译了CoreCLR,详见: 1)Windows上成功编译Cor ...

  7. eclipse下编译hadoop源代码(转)

    hadoop是一个分布式存储和分布式计算的框架.在日常使用hadoop时,我们会发现hadoop不能完全满足我们的需要,我们可能需要修改hadoop的源代码并重新编译.打包. 下面将详细描述如何从sv ...

  8. 编译Android源代码与内核总结

    这些天花了些时间自己下载了android源代码来编译,当中走了一些弯路导致耗了些时间,如今又一次梳理总结下,让有同样想法的人自己编译的时候能少走些弯路,官方指导文档在http://source.and ...

  9. 编译JDK源代码【转】

    用Eclipse Debug,当跟踪进jdk api里时(比如javax.swing包里的类),无法查看某些local filed的值.这是因为jdk里的代码在打包时删除了一些用于调试的信息,以减小安 ...

随机推荐

  1. VTK中获取STL模型点的坐标以及对其进行变换

    VTK是一个基于面向对象的开源三维绘图软件包,和其它的的三维绘图引擎如OSG.OGRE不同之处在于,VTK可视化对象主要是各种数据,更加注重对数据分析处理后的可视化,可视化的内容是人们无法直接感受到的 ...

  2. PCL中的OpenNI点云获取框架(OpenNI Grabber Framework in PCL)

    从PCL 1.0开始,PCL(三维点云处理库Point Cloud Library)提供了一个通用采集接口,这样可以方便地连接到不同的设备及其驱动.文件格式和其他数据源.PCL集成的第一个数据获取驱动 ...

  3. Excel Vlookup 列查找函数

    列查找函数语法:vlookup(lookup_value,table_array,col_index_num,[range_lookup]) lookup_value:要查找的值,数值.引用或文本字符 ...

  4. Android 本地播放器

    发布时间:2018-09-06   技术:Glide+pinyin4j+SwipeDelMenuLayout   概述 这是一款Android 端的本地音乐播放器,界面风格有模仿网易云音乐.bilib ...

  5. 使用 ODP.NET 访问 Oracle(.net如何访问Oracle)详解

    1,什么是ODF .NE,?就是Oracle 为 .NET (ODP.NET) 专门编写了 Oracle Data Provider,一个用于 Microsoft .NET 环境下的 Oracle 数 ...

  6. Android 代码画角标 offcutView

      效果如下:          代码: <com.andye.OffcutView android:layout_width="30dp" android:layout_h ...

  7. intellij idea强制更新索引

    intellij idea使用时间长了,许多包安了又卸.卸了又安,导致索引文件有些不正常. 删除~/.Intellij Idea/下的index和cache即可彻底更新.

  8. TCP_NODELAY 和 TCP_NOPUSH的解释

    一.问题的来源 今天看到 huoding 大哥分享的 lamp 面试题,其中一点提到了: Nginx 有两个配置项: TCP_NODELAY 和 TCP_NOPUSH ,请说明它们的用途及注意事项. ...

  9. 使用tmpfs的好处

    EBS上超高频率的IO写入 这几天注意到我的EC2机器上有非常大量的IO,导致AWS的总体开销增加了很多.比如9月份的帐单中: I/O requests     120,076,984 IOs     ...

  10. Linux 操作MySQL常用命令行(转)

    注意:MySQL中每个命令后都要以分号:结尾. 1.显示数据库 mysql> show databases; +----------+ | Database | +----------+ | m ...