• windows下用libevent 开发一个echo服务


    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    
    #include <iostream>
    using namespace std;
    
    #include <event2/event.h>
    #include <event2/bufferevent.h>
    
    void accept_cb(int fd, short events, void* arg);
    void socket_read_cb(bufferevent* bev, void* arg);
    void event_cb(struct bufferevent *bev, short event, void *arg);
    int tcp_server_init(int port, int listen_num);
    
    int main(int argc, char** argv)
    {
    #ifdef WIN32
        WSADATA wsa_data;
        WSAStartup(0x0201, &wsa_data);
    #endif
    
        int listener = tcp_server_init(9999, 10);
        if( listener == -1 )
        {
            perror(" tcp_server_init error ");
            return -1;
        }
    
        struct event_base* base = event_base_new();
    
        //添加监听客户端请求连接事件
        struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,
            accept_cb, base);
        event_add(ev_listen, NULL);
    
        event_base_dispatch(base);
        event_base_free(base);
    
    #ifdef WIN32
        WSACleanup();
    #endif
    
        return 0;
    }
    
    
    
    void accept_cb(int fd, short events, void* arg)
    {
        evutil_socket_t sockfd;
    
        struct sockaddr_in client;
        int len = sizeof(client);
    
        sockfd = ::accept(fd, (struct sockaddr*)&client, &len );
        evutil_make_socket_nonblocking(sockfd);
    
        cout << "accept a client " << sockfd << endl;
    
        struct event_base* base = (event_base*)arg;
    
        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 | EV_PERSIST);
    }
    
    
    
    void socket_read_cb(bufferevent* bev, void* arg)
    {
        char msg[4096] = {0};
    
        size_t len = bufferevent_read(bev, msg, sizeof(msg));
    
        cout << "recv the client msg: " << msg << endl;
        // msg[len] = '
    '; 
        // msg[len+1] = '
    '; 
    
        char reply_msg[4096] = "I have recvieced the msg: ";
    
        strcat(reply_msg + strlen(reply_msg), msg);
        bufferevent_write(bev, reply_msg, strlen(reply_msg));
    }
    
    
    
    void event_cb(struct bufferevent *bev, short event, void *arg)
    {
    
        if (event & BEV_EVENT_EOF)
        {
            cout << "connection closed" << endl;
        }
        else if (event & BEV_EVENT_ERROR)
        {
            cout << "some other error" << endl;
        }
    
        //这将自动close套接字和free读写缓冲区
        bufferevent_free(bev);
    }
    
    
    typedef struct sockaddr SA;
    int tcp_server_init(int port, int listen_num)
    {
        evutil_socket_t listener;
    
        listener = ::socket(AF_INET, SOCK_STREAM, 0);
        if( listener == -1 )
            return -1;
    
        //允许多次绑定同一个地址。要用在socket和bind之间
        evutil_make_listen_socket_reuseable(listener);
    
        do
        {
            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 )
                break;
    
            if( ::listen(listener, listen_num) < 0)
                break;
    
            //跨平台统一接口,将套接字设置为非阻塞状态
            evutil_make_socket_nonblocking(listener);
            return listener;
        } while (0);
    
        int errno_save;
        errno_save = errno;
        evutil_closesocket(listener);
        errno = errno_save;
    
        return -1;
    }
    
  • 相关阅读:
    ASP.NET Core 从入门到精通-资源收集导航
    【5分钟系列】计算机系统结构的定义
    C#反射与特性(九):全网最全-解析反射
    C#反射与特性(七):自定义特性以及应用
    C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web
    C#反射与特性(五):类型成员操作
    C#反射与特性(四):实例化类型
    C#反射与特性(三):反射类型的成员
    C#反射与特性(二):探究反射
    安卓TabLayout+ViewPager实现切页
  • 原文地址:https://www.cnblogs.com/dilex/p/10390987.html
Copyright © 2020-2023  润新知