Пример #1
0
/* do_accept: establish the new connection
 * @listenfd: the listening fd
 * @epollfd: the epollfd used to monitor the listening fd and new connected fd
 *
 * */
void do_accept(int listenfd, int epollfd)
{
    int connfd;
    struct sockaddr_in clitaddr;
    socklen_t socklen;
    //while ( (connfd = accept(listenfd,(struct sockaddr *)&clitaddr,&socklen)) > 0 )
    //{
    connfd = accept(listenfd,(struct sockaddr *)&clitaddr,&socklen);
        /* show client info */
        show_peer_info(connfd);

        /* set the connfd to non-block socket */
        //setnonblock(connfd);

        /* set the connfd events to EPOLLIN | EPLLET(edge trigger) */
        //int state =  EPOLLIN | EPOLLET;
        int state = EPOLLIN;

        /* add connected fd to epoll set */
        add_epoll_event(epollfd,connfd,state);
    //}

    /* if accept error*/
    if (connfd < 0)
    {
        if (errno != EINTR)
        {
            perror_exit("accept error");
        }
    }
}
Пример #2
0
/* handle_connection: handle the connected clients
 * @listenfd: the socket used to accept connections
 *
 * */
void handle_connection(int listenfd)
{
    /* the number of readable fds in the pollfd array */
    int nready, i;

    /* receive buffer */
    buffer_t recvbuf;
    memset(&recvbuf,0,sizeof(buffer_t));

    /* set the listenfd to non-block */
    //setnonblock(listenfd);

    /* epollfd set to monitor the related events */
    int epollfd;
    if ( (epollfd = epoll_create(EPOLL_SIZE)) < 0 )
    {
        perror_exit("epoll create error");
    }

    /* epoll event array */
    struct epoll_event events[EPOLL_EVENTS];

    /* add the listen socket to epoll set */
    int state = EPOLLIN;
    add_epoll_event(epollfd,listenfd,state);

    while( 1 )
    {
        /* obtain the ready sockets from the epoll set */
        if ( (nready = epoll_wait(epollfd,events,EPOLL_EVENTS,INFTIM)) < 0)
        {
            perror_exit("epoll wait error");
        }

        /* traverse the ready sockets */
        for (i = 0; i < nready; ++i)
        {
            int fd = events[i].data.fd;

            /* listenfd is ready */
            if ( fd == listenfd && (events[i].events & EPOLLIN) )
            {
                do_accept(listenfd, epollfd);
            }

            /* connected sockets are ready */
            else if ( events[i].events & EPOLLIN )
            {
                do_read(fd,epollfd,&recvbuf);
            }

            /* read the data from the connected socket and echo it also */
            else if ( events[i].events & EPOLLOUT )
            {
                do_write(fd,epollfd,&recvbuf);
            }
        }
    }
}
Пример #3
0
void run_client(int port)
{
    int epfd;
    int connfd;
    int rc;
    struct sockaddr_in addr;

    epfd = epoll_create(10);
    connfd = socket(AF_INET, SOCK_STREAM, 0);

    setnonblock(connfd);

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    inet_aton("127.0.0.1", &addr.sin_addr);

    rc = connect(connfd, (struct sockaddr*) &addr, sizeof(addr));
    if (rc < 0 && errno == EINPROGRESS)
        printf("connecting...\n");
    else if (rc == 0)
        printf("connected to server.\n");
    else {
        perror("connect");
    }

    add_epoll_event(epfd, connfd, EPOLLIN | EPOLLOUT);

    for ( ; ; ) {
        struct epoll_event events[32];
        int count = epoll_wait(epfd, events, 32, -1);
        int i;
        printf("%d events\n", count);
        for (i = 0; i < count; ++i) {
            int error;
            int rc;
            socklen_t len = sizeof(int);
            if (events[i].events & EPOLLOUT) {
                rc = getsockopt(events[i].data.fd, SOL_SOCKET, SO_ERROR, &error, &len);
                if (rc < 0)
                    perror("getsockopt");

                if (error == 0) {
                    printf("EPOLLOUT\n");
                } else {
                    fprintf(stderr, "could not connect to server: %s\n", strerror(error));
                }
                write(events[i].data.fd, "hi", 2);
            }
            if (events[i].events & EPOLLIN) {
                rc = getsockopt(events[i].data.fd, SOL_SOCKET, SO_ERROR, &error, &len);
                if (rc < 0)
                    perror("getsockopt");

                printf("EPOLLIN\n");
            }
            if (events[i].events & EPOLLERR) {
                printf("EPOLLERR\n");
            }
        }
    }
}
Пример #4
0
/* client handle the info received from both server and standard input
 * @connfd: the connected socket used for communication
 *
 */
void client_info(int connfd)
{
    int i;

    int shutdown_flag = 0;

    /* recv and send buffer */
    buffer_t recvbuf, sendbuf;
    memset(&recvbuf,0,sizeof(buffer_t));
    memset(&sendbuf,0,sizeof(buffer_t));

    //setnonblock(connfd);

    /* epollfd set monitors conncted socket fd and standard input, if either one is
     * readable, then we obtain the info from it*/
    int epollfd, fd;
    if ( (epollfd = epoll_create(EPOLL_SIZE)) < 0 )
    {
        perror_exit("epoll create error");
    }
    struct epoll_event events[4];
    int nready;

    add_epoll_event(epollfd,STDIN_FILENO,EPOLLIN);

    while( 1 )
    {
        if ( (nready = epoll_wait(epollfd,events,4,INFTIM)) < 0 )
        {
            perror("epollfd error");
        }

        for (i = 0; i < nready; ++i)
        {
            fd = events[i].data.fd;

            if (fd == STDIN_FILENO && (events[i].events & EPOLLIN) )
            {
                int space = buffer_hasspace(&sendbuf);
                if (space > 0)
                {
                    int nread = read(fd,&sendbuf.buffer[sendbuf.in],space);

                    /* read error */
                    if (nread < 0)
                    {
                        if (errno != EINTR)
                        {
                            perror_exit("read error");
                        }
                    }

                    else if (nread == 0)
                    {
                        /* read "ctrl+d" from client, close the connection and delete the event from epoll set */
                        shutdown_flag = 1;
                        shutdown(connfd,SHUT_WR);
                        delete_epoll_event(epollfd,fd, EPOLLIN);
                    }

                    else
                    {
                        sendbuf.in += nread;

                        /* add connection fd to epoll set */
                        add_epoll_event(epollfd,connfd,EPOLLOUT);
                    }
                }
            }

            if (fd == connfd && (events[i].events & EPOLLOUT) )
            {
                int ntotal = strlen(sendbuf.buffer);

                int nwrite = write(fd,&sendbuf.buffer[sendbuf.out],ntotal);

                if (nwrite < 0)
                {
                    perror_exit("write error");
                }

                else
                {
                    sendbuf.out += ntotal;

                    /* all data has benn sent out, reset the buffer space */
                    if (sendbuf.in == sendbuf.out)
                    {
                        buffer_reset(&sendbuf);
                    }

                    /* modify the fd from epoll set to EPOLLIN since all data has been sent out */
                    modify_epoll_event(epollfd,fd,EPOLLIN);
                }
            }

            if (fd == connfd && (events[i].events & EPOLLIN) )
            {
                int space = buffer_hasspace(&recvbuf);
                if (space > 0)
                {
                    int nread = read(fd,&recvbuf.buffer[recvbuf.in],space);

                    /* read error */
                    if (nread < 0)
                    {
                        perror_exit("read error");
                    }

                    /* read "FIN" from server */
                    else if (nread == 0)
                    {
                        /* we have sent "FIN" already */
                        if (shutdown_flag == 0)
                        {
                            printf("server terminates unexpectedly!\n");
                            exit(EXIT_FAILURE);
                        }
                        else
                            return;
                    }

                    else
                    {
                        recvbuf.in += nread;

                        /* add STDOUT_FILENO to epoll set */
                        delete_epoll_event(epollfd,connfd,EPOLLIN);
                        add_epoll_event(epollfd,STDOUT_FILENO,EPOLLOUT);
                    }
                }
            }

            if (fd == STDOUT_FILENO && (events[i].events & EPOLLOUT) )
            {
                int ntotal = strlen(recvbuf.buffer);

                int nwrite = write(fd,&recvbuf.buffer[recvbuf.out],ntotal);

                if (nwrite < 0)
                {
                    if (errno != EAGAIN)
                    {
                        perror_exit("write error");
                    }
                }

                else
                {
                    recvbuf.out += ntotal;

                    /* all data has been sent to STANDARD OUTPUT, reset
                     * the buffer space */
                    if (recvbuf.in == recvbuf.out)
                    {
                        buffer_reset(&recvbuf);

                        delete_epoll_event(epollfd,STDOUT_FILENO,EPOLLOUT);
                    }
                }
            }
        }
    }
}