zoukankan      html  css  js  c++  java
  • libevent::实现的低级 socket

    LibEvent 实现的低级 ROT13  例子
    #include <cstdio>
    #include <netinet/in.h>  
    #include <sys/socket.h>   
    #include <fcntl.h> 
    #include <event2/event.h>  
    #include <assert.h>  
    #include <unistd.h>  
    #include <string.h>   
    #include <stdlib.h> 
    #include <stdio.h>   
    #include <errno.h>  
    
    #define MAX_LINE 16384
    
    struct fd_state
    {
        char buffer[MAX_LINE];
        size_t buffer_used;
        size_t n_written;
        size_t write_upto;
        struct event*read_event;
        struct event*write_event;
    };
    
    void run(void);
    void do_accept(evutil_socket_t listener, short event, void*arg);
    struct fd_state* alloc_fd_state(struct event_base*base, evutil_socket_t fd);
    void do_read(evutil_socket_t fd, short events, void*arg);
    void do_write(evutil_socket_t fd, short events, void*arg);
    void free_fd_state(struct fd_state*state);
    
    char rot13_char(char c)
    {
        if ((c >= 'a'  &&  c <= 'm ') || (c >= 'A ' && c <= 'M '))
            return c + 13;
        else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z'))
            return c - 13;
        else
            return c;
    }
    
    int main(int c, char**v)
    {
        run();
        return 0;
    }
    
    void run(void)
    {
        evutil_socket_t listener;
        struct sockaddr_in sin;
        struct event_base*base;
        struct event*listener_event;
        base = event_base_new();
        if (!base)
            return;
    
        sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0;
        sin.sin_port = htons(9090);
        listener = socket(AF_INET, SOCK_STREAM, 0);
        evutil_make_socket_nonblocking(listener);
        /*#ifndef WIN32
            {
                int one = 1;
                setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
            }
        #endif    */
        if (bind(listener, (struct sockaddr*) &sin, sizeof(sin)) < 0)
        {
            perror("bind"); return;
        }
        if (listen(listener, 16) < 0)
        {
            perror("listen");
            return;
        }
        listener_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept, (void*)base);
    
        event_add(listener_event, NULL);
        event_base_dispatch(base);
    }
    
    void do_accept(evutil_socket_t listener, short event, void*arg)
    {
        struct event_base*base = (event_base*)(arg);
        struct sockaddr_storage ss;
        socklen_t slen = sizeof(ss);
        int fd = accept(listener, (struct sockaddr*) &ss, &slen);
        if (fd < 0)
        {
            perror("accept");
        }
        else if (fd > FD_SETSIZE)
        {
            close(fd);
        }
        else
        {
            struct fd_state* state;
    
            evutil_make_socket_nonblocking(fd);
    
            state = alloc_fd_state(base, fd);
            assert(state);
            assert(state->write_event);
            event_add(state->read_event, NULL);
        }
    }
    
    struct fd_state* alloc_fd_state(struct event_base*base, evutil_socket_t fd)
    {
        fd_state* state = (fd_state*)malloc(sizeof(fd_state));
        if (!state) return NULL;
        state->read_event = event_new(base, fd, EV_READ | EV_PERSIST, do_read, state);
        if (!state->read_event)
        {
            free(state); return NULL;
        }
        state->write_event = event_new(base, fd, EV_WRITE | EV_PERSIST, do_write, state);
        if (!state->write_event)
        {
            event_free(state->read_event);
            free(state);
            return NULL;
        }
        state->buffer_used = state->n_written = state->write_upto = 0;
        assert(state->write_event);
        return state;
    }
    
    void do_read(evutil_socket_t fd, short events, void*arg)
    {
        struct fd_state*state = (fd_state*)arg;
        int i;
        ssize_t result;
        while (1)
        {
            char buf[1024] = { '' };
            assert(state->write_event);
            result = recv(fd, buf, sizeof(buf), 0);
            if (result <= 0)
                break;
    
            printf("buf = [ %s ]
    ", buf);
    
            assert(state->write_event);
            event_add(state->write_event, NULL);
            state->write_upto = state->buffer_used;
    
            
            for (i = 0; i < result; ++i)
            {
                if (state->buffer_used < sizeof(state->buffer))
                    state->buffer[state->buffer_used++] = rot13_char(buf[i]);
    
                if (buf[i] == '
    ')
                {
                    assert(state->write_event);
                    event_add(state->write_event, NULL);
                    state->write_upto = state->buffer_used;
                }
            }
        }
        if (result == 0)
        {
            free_fd_state(state);
        }
        else if (result < 0)
        {
            if (errno == EAGAIN)
                return;
    
            perror("recv");
            free_fd_state(state);
        }
    }
    
    void do_write(evutil_socket_t fd, short events, void*arg)
    {
        struct fd_state*state = (fd_state*)arg;
        while (state->n_written < state->write_upto)
        {
            ssize_t result = send(fd, state->buffer + state->n_written, state->write_upto - state->n_written, 0);
            if (result < 0)
            {
                if (errno == EAGAIN)
                    return;
    
                free_fd_state(state);
                return;
            }
            assert(result != 0);
            state->n_written += result;
        }
        if (state->n_written == state->buffer_used)
        {
            state->n_written = state->write_upto = state->buffer_used = 1;
        }
        event_del(state->write_event);
    }
    
    
    void free_fd_state(struct fd_state*state)
    {
        event_free(state->read_event);
        event_free(state->write_event);
        free(state);
    }
  • 相关阅读:
    MySQL 工具
    MySQL 5.1参数
    CentOS 6.2下二进制安装 MySQL 5.6
    Linux 下hosts文件详解
    CentOS 6.5下二进制安装 MySQL 5.6
    云计算之云数据库
    MySQL 卸载
    Linux dig
    CentOS6.5利用Docker部署ShowDoc
    Myeclipse6.5每次打开properties中文注释都会变成乱码
  • 原文地址:https://www.cnblogs.com/osbreak/p/10280056.html
Copyright © 2011-2022 走看看