zoukankan      html  css  js  c++  java
  • libev+TCP服务器事件轮询实例demo

    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <ev.h>
     
    #define PORT            12100
    #define BUFFER_SIZE     1024
    #define MAX_LISTEN      5
     
    /*初始化服务端*/
    int server_socket_init(int *sd, char *ipaddr, uint16_t port)
    {
        //创建socket
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (-1 == sock) 
            goto err1;
        //设置立即释放端口并可以再次使用
        int reuse = 1;
        if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
            goto err2;    
        //设置为非阻塞
        if (-1 == fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK))
            goto err2;
        struct sockaddr_in addr;
        memset(&addr, 0 , sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        if (NULL == ipaddr) {
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
        } else {
            addr.sin_addr.s_addr = inet_addr(ipaddr);
        }
        //绑定监听
        if (-1 == bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
            goto err2;
        if (-1 == listen(sock, MAX_LISTEN))
            goto err2;
        *sd = sock;
        return 0;
    err2:
        close(sock);
    err1:
        return -1;
    }
     
    /*读回调*/
    void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
    {
        char buffer[BUFFER_SIZE] = {0};
        if (EV_ERROR & revents) {
          printf("read got invalid event...
    ");
          return;
        }
        int res = 0;
        int32_t bytes = read(watcher->fd, buffer, sizeof(buffer));
        if (-1 == bytes) {
            //tcp Error
            if (EINTR != errno && EAGAIN != errno) {
                res = 1;
            }
        } else if (0 == bytes) {
            //tcp Close
            res = 2;
        }
        if (0 != res) {
            //关闭事件循环并释放watcher
            printf("TCP CLOSE
    ");
            ev_io_stop(loop,watcher);
            free(watcher);
        } else {
            printf("READ:
        %s
    ", buffer);
        }
    }
     
     
    /*accept回调函数*/
    void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
    {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        if (EV_ERROR & revents) {
          printf("accept got invalid event...
    ");
          return;
        }
        //accept连接
        int sock = accept(watcher->fd, (struct sockaddr *)&client_addr, &client_len);
        if (-1 == sock) {
            return;
        }
        //设置非阻塞
        if(-1 == fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK)) {
            close(sock);
            return;
        }
        printf("Successfully connected with client: %s:%u
    ", 
        inet_ntoa(client_addr.sin_addr), client_addr.sin_port);
        //加入事件循环
        struct ev_io *w_client = (struct ev_io*) malloc (sizeof(struct ev_io));
        ev_io_init(w_client, read_cb, sock, EV_READ);
        ev_io_start(loop, w_client);
    }
     
    int main()
    {
        int sd;
        struct ev_io w_accept;
        struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
        if (NULL == loop) {
            printf("loop create failed
    ");
            return -1;
        }
        if (server_socket_init(&sd, NULL, PORT) < 0) {
            printf("server init failed
    ");
            return -1;
        }
        ev_io_init(&w_accept, accept_cb, sd, EV_READ);
        ev_io_start(loop, &w_accept);
        ev_run(loop, 0);
        return 0;
    }
     ———————————————— 
    版权声明:本文为CSDN博主「Dancer__Sky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Dancer__Sky/article/details/85159058
  • 相关阅读:
    AOP & 拦截器
    过滤器 & 监听器 & 拦截器
    @PropertySouce注解 读取 properties文件
    SpringBoot整合freemarker 引用基础
    lombok工具插件安装(idea、eclipse)
    Spring Spring boot 获取IOC中的bean,ApplicationContext
    logback 生成 catalina.base_IS_UNDEFINED 问题处理 &如何在eclipse/idea中添加VM参数
    springboot读取系统级环境变量,和读写系统属性以及unittest来获取环境变量的方法
    C#变量命名规则
    C#中的注释
  • 原文地址:https://www.cnblogs.com/nanqiang/p/11434578.html
Copyright © 2011-2022 走看看