c_cpp libevent的库TCP通信示例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp libevent的库TCP通信示例相关的知识,希望对你有一定的参考价值。

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <stdlib.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

#include <event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
//#include <event2/util.h>

static const int PORT = 8888;
static const char* IP = "127.0.0.1";

static void conn_readcb(struct bufferevent *, void *);
static void conn_writecb(struct bufferevent *, void *);
static void conn_eventcb(struct bufferevent *, short, void *);
static void cmd_msg_cb(int fd, short events, void* arg);
static void signal_cb(evutil_socket_t, short, void *);

int main() {

    struct event_base *base = event_base_new();
    if (!base) {
        fprintf(stderr, "Could not initialize libevent!\n");
        return 1;
    }

    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd < 0) {
        fprintf(stderr, "Could not initialize socket!\n");
        return 1;
    }

    struct bufferevent* bufev = bufferevent_socket_new(base, sfd, BEV_OPT_CLOSE_ON_FREE);

    //set ip and port
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    inet_pton(AF_INET, IP, &addr.sin_addr.s_addr);

    int conn_ret = bufferevent_socket_connect(bufev, (struct sockaddr*)&addr, sizeof(addr));
    if (conn_ret < 0) {
        fprintf(stderr, "Could not connect server!\n");
        return 1;
    }

    bufferevent_setcb(bufev, conn_readcb, NULL, conn_eventcb, NULL);
    bufferevent_enable(bufev, EV_READ | EV_PERSIST);

    //监听终端输入事件
    struct event* ev_cmd = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST, cmd_msg_cb, (void*)bufev);
    //上树 开始监听标准输入的读事件
    event_add(ev_cmd, NULL);

    //exit by CTRL+C (SIGINT)
    struct event *signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
    if (!signal_event || event_add(signal_event, NULL) < 0) {
        fprintf(stderr, "Could not create/add a signal event!\n");
        return 1;
    }

    //loop
    event_base_dispatch(base);

    event_free(signal_event);
    event_base_free(base);

    return 0;
}

static void conn_readcb(struct bufferevent *bufev, void *user_data) {
    char buf[128] = { 0x00 };
    int ret = bufferevent_read(bufev, buf, sizeof(buf));

    fprintf(stdout, "%s", buf);
}

static void conn_eventcb(struct bufferevent *bev, short events, void *user_data) {
    if (events & BEV_EVENT_EOF) {
        printf("Connection closed.\n");
        bufferevent_free(bev);
    } else if (events & BEV_EVENT_ERROR) {
        printf("Got an error on the connection: %s\n",
            strerror(errno));/*XXX win32*/
        bufferevent_free(bev);
    } else if (events & BEV_EVENT_CONNECTED) {
        printf("The client has Connected to server.\n");
    }
}
//终端输入回调
static 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);
}

static void signal_cb(evutil_socket_t sig, short events, void *user_data) {
    struct event_base *base = user_data;
    struct timeval delay = { 2, 0 };
    printf("Caught an interrupt signal; exiting cleanly in 2 seconds.\n");

    event_base_loopexit(base, &delay);
}
/*
static const int PORT = 8888;
static const char* IP = "127.0.0.1";
  Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
*/

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>

static const int PORT = 8888;
static const char* IP = "127.0.0.1";

static void listener_cb(struct evconnlistener *, evutil_socket_t,
    struct sockaddr *, int socklen, void *);
static void conn_readcb(struct bufferevent *, void *);
static void conn_eventcb(struct bufferevent *, short, void *);
static void signal_cb(evutil_socket_t, short, void *);

int main(int argc, char **argv) {
    struct event_base *base = event_base_new();
    if (!base) {
        fprintf(stderr, "Could not initialize libevent!\n");
        return 1;
    }

    //set ip and port
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    inet_pton(AF_INET, IP, &addr.sin_addr.s_addr);

    //socket --> listen
    struct evconnlistener *listener = evconnlistener_new_bind(base, listener_cb, (void *)base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1, (struct sockaddr*)&addr, sizeof(addr));
    if (!listener) {
        fprintf(stderr, "Could not create a listener!\n");
        return 1;
    }

    //exit by CTRL+C (SIGINT)
    struct event *signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
    if (!signal_event || event_add(signal_event, NULL) < 0) {
        fprintf(stderr, "Could not create/add a signal event!\n");
        return 1;
    }

    //loop for listen
    event_base_dispatch(base);

    evconnlistener_free(listener);
    event_free(signal_event);
    event_base_free(base);
    return 0;
}

static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,    struct sockaddr *sa, int socklen, void *user_data) {
    struct event_base *base = user_data;

    struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    if (!bev) {
        fprintf(stderr, "Error constructing bufferevent!");
        event_base_loopbreak(base);
        return;
    }
    bufferevent_setcb(bev, conn_readcb, NULL, conn_eventcb, NULL);
    bufferevent_enable(bev, EV_WRITE | EV_READ | EV_PERSIST);

    //print connect message
    struct sockaddr_in* addr = (struct sockaddr_in*)&sa;
    char buf[32] = { 0 };
    fprintf(stdout, "[%s:%d] is connected\n", inet_ntop(AF_INET, &addr->sin_addr.s_addr, buf, sizeof(buf)), htons(addr->sin_port));
}

static void conn_readcb(struct bufferevent *bev, void *user_data) {
    char buf[128] = { 0x00 };
    int ret = bufferevent_read(bev, buf, sizeof(buf));

    for (int i = 0; i < ret; i++) {
        buf[i] = toupper(buf[i]);
    }
    bufferevent_write(bev, buf, ret);
}

static void conn_eventcb(struct bufferevent *bev, short events, void *user_data) {
    if (events & BEV_EVENT_EOF) {
        printf("Connection closed.\n");
    } else if (events & BEV_EVENT_ERROR) {
        printf("Got an error on the connection: %s\n",
            strerror(errno));/*XXX win32*/
    }
    /* None of the other events can happen here, since we haven't enabled
     * timeouts */
    bufferevent_free(bev);
}

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

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

    event_base_loopexit(base, &delay);
}

以上是关于c_cpp libevent的库TCP通信示例的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 libevent 创建 tcp-client

使用 libevent 或 boost::asio 的单线程中的多个 tcp 连接。这是可能的?

c_cpp libevent_openssl

c_cpp Linux的下TCP的套接字编程示例

TCP网络编程杂谈

Linux C编程之十九 libevent基本概念