libevent的使用 32位 64位

Posted 努力,奋斗的路上!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libevent的使用 32位 64位相关的知识,希望对你有一定的参考价值。

  前段时间一个项目需要用到高并发的服务,想着自己应该可以写一个,windwos 上使用完成端口实现,写完之后,测试感觉没什么问题,可是一上线各种各样的问题,初步怀疑是底层网路库的问题,于是决定更换网络库,使用libevent 

  1,下载最新稳定版libevent

   http://libevent.org/ 目前最新稳定版本应该是libevent-2.1.8-stable.tar.gz 下载解压目录

  

  2,编译lib库

  使用VS命令提示工具编译:

  32位库的编译方法  

  cd  F:\\libevent\\libevent-2.1.8-stable

  nmake /f Makefile.nmake

  会在根目录下生成三个文件libevent_core.lib,ibevent_extras.lib,libevent.lib 

  64位库的编译方法

  首先修改Makefile.nmake 在LIBFLAGS=/nologo 后面加上 /MACHINE:X64  

  cd  F:\\libevent\\libevent-2.1.8-stable

  nmake /f Makefile.nmake

  顺利的话,根目录下同样会生成一个64位的库文件,  

  3,使用lib库

  新建一个lib文件夹,将上面编译好的lib文件放进去

  新建一个Include目录,将F:\\libevent\\libevent-2.1.8-stable\\include下的文件和文件夹copy到该目录下,F:\\libevent\\libevent-2.1.8-stable\\WIN32-Code下的文件copy到该目录下,2个event2目录下的文件可合并一起。

  然后,在项目工程中引用该include 和lib

#ifndef WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
#  include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif

#include "event2/bufferevent.h"
#include "event2/buffer.h"
#include "event2/listener.h"
#include "event2/util.h"
#include "event2/event.h"

#include <WinSock2.h>

string IP = "127.0.0.1";
int PORT = 9500;
char * pMessage = "hello client";


struct bevdata
{
    string ip;
    int port;
};
static void conn_readcb(struct bufferevent *bev, void *ctx)
{
    bevdata *pbev_data = (bevdata*)ctx;
    struct evbuffer* input = bufferevent_get_input(bev); 
    size_t len = evbuffer_get_length(input);
    printf("point = %x,len = %d",bev,len);
    struct evbuffer* output = bufferevent_get_output(bev);
    char msg[4096] = {0};
    len = bufferevent_read(bev, msg, sizeof(msg) - 1);

    printf("server recv data : %s:%d %s\\n",pbev_data->ip.c_str(),pbev_data->port,msg);
    char senddata[20];
    strcpy(senddata,"i recv your data");
    bufferevent_write(bev,senddata,strlen(senddata));
}
static void conn_writecb(struct bufferevent *bev, void *ctx)
{


}
static void conn_eventcb(struct bufferevent *bev, short what, void *ctx)
{
    if (what & BEV_EVENT_EOF) {
        printf("connection closed\\n");
    }
    else if (what & BEV_EVENT_ERROR) {
        printf("some other error\\n");
    }

    bufferevent_free(bev);

}
static void signal_cb(evutil_socket_t sig, short events, void *user_data)
{
    struct event_base *base = (struct event_base *)user_data;
    struct timeval delay = { 2, 0 };

    printf("Caught an interrupt signal; exiting cleanly in two seconds.\\n");

    event_base_loopexit(base, &delay);
}
static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *user_data)
{
    struct event_base * base = (struct event_base *)user_data;
    struct bufferevent * bev;

    bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
    if(!bev)
    {
        printf("error constructing bufferevent\\n");
        event_base_loopbreak(base);
        return ;
    }
    char temp[1024] = {0};
    // 将sockaddr强制转换为 sockaddr_in
    sockaddr_in sin;
    memcpy(&sin, sa, sizeof(sin));
    // 取得ip和端口号
    sprintf(temp, inet_ntoa(sin.sin_addr));
    bevdata *bev_data = new bevdata;
    bev_data->ip = temp;
    bev_data->port = sin.sin_port;
    printf("address = %s,port = %d,%x\\n",temp,sin.sin_port,bev);
    bufferevent_setcb(bev,conn_readcb,conn_writecb,conn_eventcb,bev_data);
    bufferevent_enable(bev, EV_WRITE);
    bufferevent_enable(bev, EV_READ);

    bufferevent_write(bev,pMessage,strlen(pMessage));
}
int _tmain(int argc, _TCHAR* argv[])
{

    /*CCompleteIOWrapper complete ;
    complete.initComplete("127.0.0.1",9500);
    complete.startComplete();

    getchar();
    */
    struct event_base * base;
    struct evconnlistener * listener;
    struct event * signal_event;
    struct sockaddr_in sin;
#ifdef WIN32
    WSADATA wsa_data;
    WSAStartup(0x0201,&wsa_data);
#endif

    base = event_base_new();
    if(!base)
    {
        printf("cannot initailize libevent\\n");
        return 1;
    }
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);
    sin.sin_addr.S_un.S_addr = inet_addr(IP.c_str());

    listener = evconnlistener_new_bind(base,listener_cb,(void*)base,
        LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,-1,
        (struct sockaddr*)&sin,
        sizeof(sin));
    if(!listener)
    {
        printf("can not create a listener\\n");
        return 0;
    }
    signal_event = evsignal_new(base,SIGINT,signal_cb,(void*)base);
    if(!signal_event)
    {
        printf("can not create a signal event\\n");
        return 0;
    }
    printf("sertver starting...\\n");
    event_base_dispatch(base);

    evconnlistener_free(listener);
    event_free(signal_event);
    event_base_free(base);
    printf("done\\n");
    
    return 0;
}

  5,编译好的库文件,奉献给大家 https://files.cnblogs.com/files/techdreaming/lib.zip

以上是关于libevent的使用 32位 64位的主要内容,如果未能解决你的问题,请参考以下文章

从 64 位进程调用 32 位代码

从顶点到片段着色器的平滑 64 位输入 - “错误 C7570:64 位输入应该是平坦的”

将 32 位库链接到 64 位程序

使用 g++ -march=x86-64 构建的代码可以在 32 位操作系统上运行吗?

Android 逆向IDA 工具使用 ( IDA 32 位 / 64 位 版本 | 汇编代码视图 IDA View-A | 字符串窗口 Strings window )

Android 逆向IDA 工具使用 ( IDA 32 位 / 64 位 版本 | 汇编代码视图 IDA View-A | 字符串窗口 Strings window )