当前位置:   article > 正文

Libevent实现server的三种方法,原生socket event 、bufferevent 、evconnlistener_new_bind_libevent server

libevent server

参考文章
可以用上篇文章的poll client进行测试

bufferevent 帮我们更好的处理单纯的读写操作
evconnlistener_new_bind内部帮我们使用了socket的accept bind等函数
带有定时器超过时间没有读写操作就将断开连接。
bufferevent_set_timeouts

#include <iostream>
#include <curl/curl.h>
#include <assert.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
#include <event2/thread.h>
#include <sys/types.h>
#include <error.h>
#include <unistd.h>
#include <string.h>


void event_cb(struct bufferevent* bev, short event, void * arg )
{
    if ( event & BEV_EVENT_TIMEOUT )
        printf("client timeout\n");
    else if ( event & BEV_EVENT_EOF )
        printf("connection closed\n");
    else if ( event & BEV_EVENT_ERROR )
        printf("some other error\n");

    bufferevent_free(bev);
}

void socket_read_cb(struct bufferevent* bev, void *arg)
{
    char msg[4096];
    size_t len = bufferevent_read(bev,msg,sizeof(msg));
    msg[len] = '\0';
    printf("recv the client msg: %s\n",msg);

    char reply_msg[4096] = " received the msg : ";

    strcat(reply_msg+ strlen(reply_msg),msg);
    bufferevent_write(bev,reply_msg, strlen(reply_msg));
}

void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
                 struct sockaddr*sock, int socklen, void*arg)
{
    printf("accapt a client %d \n",fd);
    struct event_base* base = (struct event_base *)arg;
    struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev,socket_read_cb,NULL,event_cb,NULL);
    bufferevent_enable(bev,EV_READ | EV_PERSIST);
    struct timeval tv = {10,0};
    bufferevent_set_timeouts (bev, &tv, 0);
}

typedef struct sockaddr SA;
int tcp_server_init(int port, int listen_num)
{
    int errno_save;
    evutil_socket_t listener;

    listener = ::socket(AF_INET, SOCK_STREAM, 0);
    if( listener == -1 )
        return -1;

    //允许多次绑定同一个地址。要用在socket和bind之间
    evutil_make_listen_socket_reuseable(listener);

    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = 0;
    sin.sin_port = htons(port);

    if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )
        goto error;

    if( ::listen(listener, listen_num) < 0)
        goto error;


    //跨平台统一接口,将套接字设置为非阻塞状态
    evutil_make_socket_nonblocking(listener);

    return listener;

    error:
    errno_save = errno;
    evutil_closesocket(listener);
    errno = errno_save;

    return -1;
}

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);
    }

    int sockfd = *((int*)arg);

    //把终端的消息发送给服务器端
    //为了简单起见,不考虑写一半数据的情况
    write(sockfd, msg, ret);
}

void socket_read_cb(int fd , short  events , void * arg )
{
    char msg[4096];
    int len = read(fd, msg, sizeof(msg) - 1);

    if(len <= 0)
    {
        printf("some error happen when read\n");
        return;
    }
    msg[len] = '\0';
    printf("recv the client msg : %s\n", msg);
}

void accept_cb(int fd , short events , void * arg )
{
    evutil_socket_t sockfd;

    struct sockaddr_in client;
    socklen_t len = sizeof(client);

    sockfd = ::accept(fd, (struct sockaddr*)&client, &len);
    evutil_make_socket_nonblocking(sockfd);

    printf("accept a client %d\n", sockfd);
    struct event_base* base = (event_base*)arg;
    /*
     * 很堵,被STDIN堵住了
    //动态创建一个event结构体,并将其作为回调参数传递给
    struct event* ev2 = event_new(NULL, -1, 0, NULL, NULL);
    struct event* ev = event_new(NULL, -1, 0, NULL, NULL);
    event_assign(ev2, base, STDIN_FILENO, EV_WRITE  | EV_PERSIST, cmd_msg_cb, (void *)&sockfd);
    event_assign(ev, base, sockfd, EV_READ | EV_PERSIST, socket_read_cb, NULL);
    event_add(ev, NULL);
    event_add(ev2,NULL);
     */
    struct bufferevent* bev = bufferevent_socket_new(base,sockfd,BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev,socket_read_cb,NULL, event_cb,arg);
    bufferevent_enable(bev,EV_READ );
}

int main() {
    /*
    int listener = tcp_server_init(5000,10);
    assert(listener != -1 );
    struct event_base *base = event_base_new();
    assert(base != NULL);
    //creatfifo((void*)base);
    struct event* listen_event;
    listen_event = event_new(base,listener,EV_READ|EV_WRITE|EV_PERSIST,accept_cb,(void*)base);
    */
    struct sockaddr_in sin ;
    memset(&sin,0,sizeof(struct  sockaddr_in));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    struct  event_base *base = event_base_new();
    struct evconnlistener * listener = evconnlistener_new_bind(base,listener_cb,base,
             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;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/742729
推荐阅读
相关标签
  

闽ICP备14008679号