to myself 的分类学习日志

做自己想做的事
posts - 232, comments - 6, trackbacks - 0, articles - 0

libev simple server and client

Posted on 2015-07-03 19:14 kongkongzi 阅读(674) 评论(0)  编辑 收藏 引用 所属分类: c++ network library
实现功能:client从标准输入读取输入,发送到server;server收到client的消息后,原样发给client。

libev simple server
/*
 * example_server.c
 
*/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <netinet/in.h>
#include <strings.h>
#include "ev.h"

#define PORT 8333
#define BUFFER_SIZE 1024
#define MAX_ALLOWED_CLIENT 10240

struct ev_io *libevlist[MAX_ALLOWED_CLIENT] = { NULL };

// gcc example_server.c ev.o -lm
void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
int freelibev(struct ev_loop *loop, int fd);

int main()
{
    struct ev_loop *loop = ev_default_loop(0);
    int sd;
    struct sockaddr_in addr;
    int addr_len = sizeof(addr);
    struct ev_io socket_watcher;
    ev_timer timeout_watcher;

    if ((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("socket error. errno:%d\n", errno);
        return -1;
    }

    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != 0)
    {
        printf("bind error.errno:%d\n", errno);
    }

    if (listen(sd, 2) < 0)
    {
        printf("listen error\n");
        return -1;
    }

    printf("ev_loop beg\n");

    ev_io_init(&socket_watcher, accept_cb, sd, EV_READ);
    ev_io_start(loop, &socket_watcher);

    printf("ev_loop start\n");
    ev_loop(loop, 0);
    printf("ev_loop end\n");

    return 0;
}


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);
    int client_sd;
    struct ev_io *w_client = (struct ev_io*) malloc(sizeof(struct ev_io));

    if (EV_ERROR & revents)
    {
        printf("error event in accept\n");
        return;
    }

    client_sd = accept(watcher->fd, (struct sockaddr *) &client_addr,
            &client_len);
    if (client_sd < 0)
    {
        printf("accept error\n");
        return;
    }

    //如果连接数超出指定范围,则关闭连接
    if (client_sd > MAX_ALLOWED_CLIENT)
    {
        printf("fd too large[%d]\n", client_sd);
        close(client_sd);
        return;
    }

    if (libevlist[client_sd] != NULL)
    {
        printf("client_sd not NULL fd is [%d]\n", client_sd);
        return;
    }

    printf("someone connected.\n");
    ev_io_init(w_client, read_cb, client_sd, EV_READ);
    ev_io_start(loop, w_client);

    libevlist[client_sd] = w_client;
}


void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    char buffer[BUFFER_SIZE];
    ssize_t read;
    if (EV_ERROR & revents)
    {
        printf("error event in read");
        return;
    }

    read = recv(watcher->fd, buffer, BUFFER_SIZE, 0);
    if (read < 0)
    {
        printf("read error,errno:%d\n", errno);
        return;
    }

    if (read == 0)
    {
        printf("someone disconnected, errno:%d\n", errno);
        freelibev(loop, watcher->fd);
        return;
    }
    else
    {
        printf("get the message:%s\n", buffer);
    }

    send(watcher->fd, buffer, read, 0);
    bzero(buffer, read);
}


int freelibev(struct ev_loop *loop, int fd)
{
    if(libevlist[fd] == NULL)
    {
        printf("the fd already freed[%d]\n", fd);
        return -1;
    }

    close(fd);
    ev_io_stop(loop, libevlist[fd]);
    free(libevlist[fd]);
    libevlist[fd] = NULL;
    return 1;
}

libev simple client
/*
 * example_client.c
 *
 
*/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "ev.h"

#define PORT 8333
#define BUFFER_SIZE 1024


// gcc example_client.c ev.o -lm
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
void stdin_cb(EV_P_ ev_io *w, int revents);


int g_server_sockfd;

int main()
{
    struct ev_loop *loop = ev_default_loop(0);

    struct hostent *he; /*  主机信息 */
    struct sockaddr_in their_addr; /*  对方地址信息 */

    /*  get the host info */
    if ((he = gethostbyname("127.0.0.1")) == NULL)
    {
        /*  注意:获取DNS信息时,显示出错需要用herror而不是perror */
        herror("gethostbyname");
        exit(1);
    }

    if ((g_server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(1);
    }

    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(PORT); /*  short, NBO */
    their_addr.sin_addr = *((struct in_addr *) he->h_addr);
    bzero(&(their_addr.sin_zero), 8); /*  其余部分设成0 */
    if (connect(g_server_sockfd, (struct sockaddr *) &their_addr,
            sizeof(struct sockaddr)) == -1)
    {
        perror("connect");
        exit(1);
    }

    ev_io w_client;
    ev_io_init(&w_client, read_cb, g_server_sockfd, EV_READ);
    ev_io_start(loop, &w_client);

    ev_io stdin_watcher;
    ev_io_init(&stdin_watcher, stdin_cb, STDIN_FILENO, EV_READ);
    ev_io_start(loop, &stdin_watcher);

    printf("ev_loop start\n");
    ev_loop(loop, 0);
    printf("ev_loop end\n");

    close(g_server_sockfd);
    return 0;
}


void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    char buffer[BUFFER_SIZE];
    ssize_t len;
    if (EV_ERROR & revents)
    {
        printf("error event in read");
        return;
    }

    len = recv(watcher->fd, buffer, BUFFER_SIZE, 0);
    if (len < 0)
    {
        printf("network read error,errno:%d\n", errno);
        return;
    }

    if (len == 0)
    {
        printf("someone disconnected.errno:%d\n", errno);
        close(watcher->fd);
        ev_io_stop(loop, watcher);
        free(watcher);
        return;
    }
    else
    {
        printf("get the message:%s\n", buffer);
        if (strcmp("quit",  buffer) == 0)
        {
            ev_io_stop(EV_A_ watcher);
            // to stop network io event
            ev_break(EV_A_ EVBREAK_CANCEL);
        }
    }
}


void stdin_cb(EV_P_ ev_io *w, int revents)
{
    char buffer[BUFFER_SIZE];
    bzero(buffer, BUFFER_SIZE);
    ssize_t len;
    if (EV_ERROR & revents)
    {
        printf("error event in read");
        return;
    }

    // w->fd: STDIN_FILENO
    
// len = recv(w->fd, buffer, sizeof(buffer), 0); // wrong??
    len = read(w->fd, buffer, sizeof(buffer)); // right
    if (len <= 0)
    {
        printf("stdin read error, return:%ld, errno:%d\n", len, errno);
        return;
    }

    if ('\n' == buffer[len-1])
    {
        buffer[len-1] = '\0';
        if ('\r' == buffer[len-2])
        {
            buffer[len-2] = '\0';
            len--;
        }
    }

    send(g_server_sockfd, buffer, len, 0);
    if (strcmp("quit",  buffer) == 0)
    {
        ev_io_stop(EV_A_ w);
        // to stop network io event
        ev_break(EV_A_ EVBREAK_CANCEL);
    }
    bzero(buffer, len);
}




只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理