win7下libevent实现的rot13服务器

来源:互联网 发布:博购软件 编辑:程序博客网 时间:2024/04/28 20:45
// libev_rot13.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <event2/event.h>#include <assert.h>#define MAX_LINE 16384void do_read(evutil_socket_t fd, short events, void *arg);void do_write(evutil_socket_t fd, short events, void *arg);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;}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;};struct fd_state * alloc_fd_state(struct event_base *base, evutil_socket_t fd){    struct fd_state *state = (struct fd_state *)malloc(sizeof(struct 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 free_fd_state(struct fd_state *state){    event_free(state->read_event);    event_free(state->write_event);    free(state);}void do_read(evutil_socket_t fd, short events, void *arg){    struct fd_state *state = (struct fd_state *)arg;char buf[1024] = {0};    int i;    size_t result = 0;    while (1) {        assert(state->write_event);        result = recv(fd, buf, sizeof(buf), 0);        if (result == SOCKET_ERROR)            break;        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] == '\n') {                assert(state->write_event);                event_add(state->write_event, NULL);                state->write_upto = state->buffer_used;            }        }    }    if (result == 0) {perror("read error");        free_fd_state(state);    } else if (result < 0) {        if (WSAGetLastError() == WSAEWOULDBLOCK) // XXXX use evutil macro            return;        perror("recv");        free_fd_state(state);    }}void do_write(evutil_socket_t fd, short events, void *arg){    struct fd_state *state = (struct fd_state *)arg;    while (state->n_written < state->write_upto) {        int result = send(fd, state->buffer + state->n_written,                              state->write_upto - state->n_written, 0);        if (result == SOCKET_ERROR) {if (WSAGetLastError() == WSAEWOULDBLOCK) // XXX use evutil macro                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 do_accept(evutil_socket_t listener, short event, void *arg){    struct event_base *base = (struct event_base *)arg;    struct sockaddr_storage ss;    int slen = sizeof(ss);    int fd = accept(listener, (struct sockaddr*)&ss, &slen);    if (fd == INVALID_SOCKET) {        perror("accept");    }  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);    }}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(40713);    listener = socket(AF_INET, SOCK_STREAM, 0);    evutil_make_socket_nonblocking(listener);    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);}int main(int c, char **v){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return -1;}    setvbuf(stdout, NULL, _IONBF, 0);    run();WSACleanup();    return 0;}


工作过程

WSAStartup()

event_base_new()   新建一个event loop

创建侦听socket,并调用evutil_make_socket_nonblocking,设置为非阻塞。

bind

listen

event_new  创建侦听socket的事件对象,置EV_READ|EV_PERSIST标志位表明是感兴趣读事件,并设置listen socket的read callback。当调用到这个callback的时候,说明有外来连接到来。

event_add  将新创建的event事件对象加入到eventloop中。

event_base_dispatch  开始处理请求。


do_accept过程

accept  接收一个连接

evutil_make_socket_nonblocking    设置新socket为非阻塞。

针对新收到的socket,创建read event和write event,并分配存储区存储会话过程中的数据。

event_add   将socket的read event加入到event loop中。 当这个socket收到数据时,会调用到do_read


do_read过程

recv  接收数据

处理数据,直至一段数据end。

event_add 将socket的write event加入到event loop中,开始回送response。


do_write过程

send  发送数据

event_del  发送完成后,将write event从event loop中删除。


0 0