linux epoll

  今天实验了下 异步连接 是不是可行  答案是肯定的  顺便看了下  epoll 的使用 。。和 windows 上的 IOCP 不一样的时候 一旦数据可读了 那么你就要一直 read 到不可读为止 ,。。。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <sys/ioctl.h>

char *msg = "GET / http/1.1\r\n\r\n";

uint32_t DNS(const char *hostname)
{
    uint32_t ret = -1;
    u_char answer[256];
    int len = 0;
    ns_msg msg;
    ns_rr rr;
    res_init();
    if ((len = res_query(hostname, ns_c_in, ns_t_a, &answer[0], sizeof(answer))))
    {
        int j ;
        ns_initparse (answer, len, &msg);
        len = ns_msg_count (msg, ns_s_an);
        for (j = 0; j < len; j++)
        {
            //char dispbuf[256];
            ns_parserr (&msg, ns_s_an, j, &rr);
            //ns_sprintrr (&msg, &rr, NULL, NULL, dispbuf, sizeof (dispbuf));
            //printf ("%s\n", dispbuf);
            if (ns_t_a == ns_rr_type(rr))
            {
                struct in_addr in;
                printf("name:%s\n", ns_rr_name(rr));
                in.s_addr = htonl(ns_get32(ns_rr_rdata(rr)));
                printf("ip:%s\n", inet_ntoa(in));
                ret = in.s_addr;
            }
        }
    }
    return ret;
}

int  add2epoll(int fd, int epoll_fd)
{
    struct epoll_event ev;
    ev.data.fd = fd;
    //ev.data.ptr = "i am sincoder";//
    ev.events = EPOLLIN  | EPOLLOUT | EPOLLERR | EPOLLET ;
    return epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
}

int del_from_epoll(int fd, int epoll_fd)
{
    return epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
}

static int isconnect = 1;

int main(int argc, char **argv)
{
    int epoll_fd;
    struct sockaddr_in addr;
    int sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK , IPPROTO_TCP);
    if (-1 == sock)
    {
        fprintf(stderr, "create socket failed \n" );
        return -1;
    }
    epoll_fd = epoll_create(100);
    if (epoll_fd == -1)
    {
        close(sock);
        perror("epoll_create:");
        return -1;
    }
    if (-1 != add2epoll(sock, epoll_fd))
    {
        addr.sin_addr.s_addr = DNS("www.baidu.com");
        addr.sin_port = htons(80);
        addr.sin_family = AF_INET;
        if (-1 != connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr)) || errno == EINPROGRESS)
        {
            int nr_events;
            struct epoll_event *events = NULL;
            events = malloc (sizeof (struct epoll_event) * 64);
            if (!events)
            {
                perror ("malloc():");
                return 0;
            }

            while (1)
            {
                int i = 0;
                printf("enter wait !\n");
                nr_events = epoll_wait (epoll_fd, events, 64, -1);
                printf("out wait  %d\n", nr_events);

                if (nr_events < 0)
                {
                    perror("epoll_wait");
                }

                for (i = 0; i < nr_events; i++)
                {
                    if (events[i].events & EPOLLERR)
                    {
                        printf("EPOLLERR ");
                        printf("remote close ?? \n");
                        if (-1 == del_from_epoll(events[i].data.fd, epoll_fd))
                        {
                            perror("epoll_ctrl():");
                        }
                        close(events[i].data.fd);

                        events[i].events &= ~EPOLLERR;
                    }
                    if (events[i].events & EPOLLIN)
                    {
                        int len = 0;
                        char buff[1024];
                        printf("EPOLLIN ");
                        while (1)
                        {
                            len = read(events[i].data.fd, buff, 1000);
                            if (len > 0)
                            {
                                buff[len] = 0;
                                printf("recv %d bytes : %s \n", len, buff );
                            }
                            else
                            {
                            	if(errno == EAGAIN || errno == EWOULDBLOCK)
                            		break;
                                perror("recv():");
                                printf("socket close ???\n");
                                break;
                            }
                        }
                        events[i].events &= ~EPOLLIN;
                    }
                    if (events[i].events & EPOLLOUT)
                    {
                        printf("EPOLLOUT ");
                        if (isconnect)
                        {
                            write(sock, msg, strlen(msg));
                            isconnect = 0;
                        }
                        events[i].events &= ~EPOLLOUT;
                    }

                    if (0 != events[i].events)
                    {
                        printf("there is a unknown msg : %d \n", events[i].events);
                    }
                }
            }
        }
        else
        {
            printf("connect failed %d %s\n", errno, strerror(errno));
        }
    }
    else
        perror("epoll():");
    close(sock);
    close(epoll_fd);
    return 0;
}

你可能感兴趣的:(linux epoll)