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...\r\n");
      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\r\n");
        ev_io_stop(loop,watcher);
        free(watcher);
    } else {
        printf("READ:\r\n    %s\r\n", 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...\r\n");
      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\r\n", \
    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\r\n");
        return -1;
    }
    if (server_socket_init(&sd, NULL, PORT) < 0) {
        printf("server init failed\r\n");
        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

 

转载于:https://www.cnblogs.com/nanqiang/p/11434578.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值