移植libevent到ARM开发板并测试

1.移植移植libevent

到官网下载https://libevent.org/  libevent-2.1.12-stable.tar.gz 或  libevent-2.1.10-stable.tar.gz

解压tar -zxvf libevent-2.1.12-stable.tar.gz

进入解压目录:cd libevent-2.1.12-stable/

配置编译工具链: ./configure --prefix=/home/jest/libevent --host=arm-linux-gnueabihf CC=/xxx/xxx/xxx/arm-linux-gnueabihf-gcc CXX=/xxx/xxx/xxx/arm-linux-gnueabihf-g++ ("/xxx/xxx/xxx/"为存放工具链的目录)

执行后出现错误:

没有找到openssl,那么可以disable openssl功能(如果使用是libevent-2.1.10-stable.tar.gz以下版本是没有这个错误)

这样配置编译工具链:./configure --prefix=/home/jest/libevent --host=arm-linux-gnueabihf CC=/xxx/xxx/xxx/arm-linux-gnueabihf-gcc CXX=/xxx/xxx/xxx/arm-linux-gnueabihf-g++ --disable-openssl,执行成功

  make -j4 (4核编译)

  make install

2.测试libevent(server是一个echo服务器)

服务端代码:server.c

#include<netinet/in.h>
#include<sys/socket.h>
#include<unistd.h>
 
#include<stdio.h>
#include<string.h>
 
#include<event.h>
#include<event2/listener.h>
#include<event2/bufferevent.h>
#include<event2/thread.h>
 
void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
        struct sockaddr*sock, int socklen, void*arg);
 
void socket_read_cb(struct bufferevent*bev, void*arg);
void socket_event_cb(struct bufferevent*bev, short events, void*arg);
 
int main() {
    //evthread_use_pthreads();//enable threads
 
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(struct sockaddr_in));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(9999);
 
    struct event_base*base = event_base_new();
    struct evconnlistener *listener = evconnlistener_new_bind(base, listener_cb, base,
            LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, 10,
            (struct sockaddr*) &sin, sizeof(struct sockaddr_in));
    //事件循环开始
    event_base_dispatch(base);
 
    evconnlistener_free(listener);
    event_base_free(base);
    return 0;
}
 
/*
 * 当新客户端连接上服务器,此函数被调用,libevent已经帮助accept了此客户端,该客户端的文件描述符位fd
 */
void listener_cb(struct evconnlistener*listener, evutil_socket_t fd,
        struct sockaddr*sock, int socklen, void*arg) {
    printf("accept a client %d\n", fd);
 
    struct event_base*base = (struct event_base*) arg;
    //为此客户端分配一个bufferevent
    struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);
    bufferevent_enable(bev, EV_READ | EV_PERSIST);
}
 
void socket_read_cb(struct bufferevent*bev, void*arg) {
    char msg[4096];
 
    size_t len = bufferevent_read(bev, msg, sizeof(msg) - 1);
    msg[len] = '\0';
    printf("server read the data %s\n", msg);
 
    char reply[] = "I have read your data";
    bufferevent_write(bev, reply, strlen(reply));
}
 
void socket_event_cb(struct bufferevent*bev, short events, void*arg) {
    if (events & BEV_EVENT_EOF) {
        printf("connection closed\n");
    } else if (events & BEV_EVENT_ERROR) {
        printf("some other error\n");
    }
    //自动关闭套接字和释放读写缓冲区
    bufferevent_free(bev);
}

客户端代码:client.c

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#include<unistd.h>
 
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
 
#include<event.h>
#include<event2/bufferevent.h>
#include<event2/buffer.h>
#include<event2/util.h>
 
int tcp_connect_server(const char*server_ip, int port);
 
void cmd_msg_cb(int fd, short events, void*arg);
void server_msg_cb(struct bufferevent*bev, void*arg);
void event_cb(struct bufferevent*bev, short event, void*arg);
 
int main(int argc, char**argv) {
    if (argc < 3) {
        //2param
        printf("please input 2 parameter:ip_addr port\n");
        return -1;
    }
 
    struct event_base*base = event_base_new();
    struct bufferevent*bev = bufferevent_socket_new(base, -1,
            BEV_OPT_CLOSE_ON_FREE);
    //监听终端输入事件
    struct event*ev_cmd = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST,
            cmd_msg_cb, (void*) bev);
    event_add(ev_cmd, NULL);
 
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    inet_aton(argv[1], &server_addr.sin_addr);
    bufferevent_socket_connect(bev, (struct sockaddr*) &server_addr,
            sizeof(server_addr));
    bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*) ev_cmd);
    bufferevent_enable(bev, EV_READ | EV_PERSIST);
 
    event_base_dispatch(base);
    printf("finished \n");
    return 0;
}
 
void cmd_msg_cb(int fd, short events, void*arg) {
    char msg[1024];
    int ret = read(fd, msg, sizeof(msg));
    if (ret < 0) {
        perror("read fail ");
        exit(1);
    }
 
    struct bufferevent*bev = (struct bufferevent*) arg;
    //把终端的消息发送给服务器端
    bufferevent_write(bev, msg, ret);
}
 
void server_msg_cb(struct bufferevent*bev, void*arg) {
    char msg[1024];
    size_t len = bufferevent_read(bev, msg, sizeof(msg));
    msg[len] = '\0';
    printf("recv %s from server \n", msg);
}
 
void event_cb(struct bufferevent* bev, short event, void*arg) {
    if (event & BEV_EVENT_EOF) {
        printf("connection closed\n");
    } else if (event & BEV_EVENT_ERROR) {
        printf("some other error\n");
    } else if (event & BEV_EVENT_CONNECTED) {
        printf("the client has connected to server\n");
        return;
    }
    //自动关闭套接字和清空缓冲区
    bufferevent_free(bev);
 
    struct event*ev = (struct event*) arg;
    event_free(ev);
}

编译脚本:

将/home/jest/libevent目录的lib与include拷贝到测试源码的libevent2.1.12-arm目录,编写编译脚本build.sh如下

arm-linux-gnueabihf-gcc ./server.c -o server.out -I./ -I./libevent2.1.12-arm/include/event2 -I./libevent2.1.12-arm/include ./libevent2.1.12-arm/lib/libevent.a  -lrt -lpthread 
arm-linux-gnueabihf-gcc ./client.c -o client.out -I./ -I./libevent2.1.12-arm/include/event2 -I./libevent2.1.12-arm/include ./libevent2.1.12-arm/lib/libevent.a -lpthread 

更改为可执行权限后执行build.sh,将server.out client.out放入板子后验证

server:

client1:

 

client2:

 

posted @ 2020-11-27 15:14  jest549  阅读(891)  评论(0编辑  收藏  举报