第九章 两种模式的比较

来源:互联网 发布:js中动态生成表格 编辑:程序博客网 时间:2024/06/04 18:06




#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <assert.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <stdlib.h>#include <sys/epoll.h>#include <pthread.h>#define MAX_EVENT_NUMBER 1024#define BUFFER_SIZE 10int setnonblocking( int fd )//修改文件描述符的属性为非阻塞,并返回原属性{    int old_option = fcntl( fd, F_GETFL );    int new_option = old_option | O_NONBLOCK;    fcntl( fd, F_SETFL, new_option );    return old_option;}void addfd( int epollfd, int fd, bool enable_et )//在内核注册表epollfd上注册fd上的EPOLLIN和EPOLLET(根据enable_et决定)事件{    epoll_event event;    event.data.fd = fd;    event.events = EPOLLIN;    if( enable_et )    {        event.events |= EPOLLET;    }    epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );    setnonblocking( fd );}void lt( epoll_event* events, int number, int epollfd, int listenfd ){    char buf[ BUFFER_SIZE ];    for ( int i = 0; i < number; i++ )    {        int sockfd = events[i].data.fd;        if ( sockfd == listenfd )        {            struct sockaddr_in client_address;            socklen_t client_addrlength = sizeof( client_address );            int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );            addfd( epollfd, connfd, false );//这里是与et模式的产生差别的原因        }        else if ( events[i].events & EPOLLIN )        {            printf( "event trigger once\n" );            memset( buf, '\0', BUFFER_SIZE );            int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );            if( ret <= 0 )            {                close( sockfd );                continue;            }            printf( "get %d bytes of content: %s\n", ret, buf );        }        else        {            printf( "something else happened \n" );        }    }}void et( epoll_event* events, int number, int epollfd, int listenfd ){    char buf[ BUFFER_SIZE ];    for ( int i = 0; i < number; i++ )    {        int sockfd = events[i].data.fd;        if ( sockfd == listenfd )        {            struct sockaddr_in client_address;            socklen_t client_addrlength = sizeof( client_address );            int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );            addfd( epollfd, connfd, true );        }        else if ( events[i].events & EPOLLIN )        {            printf( "event trigger once\n" );            while( 1 )//因为不阻塞等待故要一次读完            {                memset( buf, '\0', BUFFER_SIZE );                int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );                if( ret < 0 )                {//出错                    if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) )                    {                        printf( "read later\n" );                        break;                    }                    close( sockfd );                    break;                }                else if( ret == 0 )                {//客户端关闭                    close( sockfd );                }                else                {//成功                    printf( "get %d bytes of content: %s\n", ret, buf );                }            }        }        else        {            printf( "something else happened \n" );        }    }}int main( int argc, char* argv[] ){    if( argc <= 2 )    {        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );        return 1;    }    const char* ip = argv[1];    int port = atoi( argv[2] );    int ret = 0;//设置服务器地址属性    struct sockaddr_in address;    bzero( &address, sizeof( address ) );    address.sin_family = AF_INET;    inet_pton( AF_INET, ip, &address.sin_addr );    address.sin_port = htons( port );//listenfd是服务器端socket文件描述符    int listenfd = socket( PF_INET, SOCK_STREAM, 0 );    assert( listenfd >= 0 );//绑定地址    ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );    assert( ret != -1 );//设置监听    ret = listen( listenfd, 5 );    assert( ret != -1 );//创建内核事件注册表epollfd    epoll_event events[ MAX_EVENT_NUMBER ];    int epollfd = epoll_create( 5 );    assert( epollfd != -1 );    addfd( epollfd, listenfd, true );    while( 1 )    {        int ret = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );//监听内核注册表epollfd上的事件        if ( ret < 0 )        {            printf( "epoll failure\n" );            break;        }//比较两种模式        lt( events, ret, epollfd, listenfd );        //et( events, ret, epollfd, listenfd );    }    close( listenfd );    return 0;}


0 0