Linux----网络编程(ET模式与LT模式的区别及代码演示)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41026740/article/details/83422775

 

epoll对文件描述符的操作有两种模式:LT模式和ET模式。

LT模式(普通模式):也叫水平触发。描述符上有数据就绪,如果用户没有处理完,可以反复提醒,当下一轮IO函数执行时会继续提醒用户该描述符上有数据,直到用户将数据读完为止。

ET模式(高效模式):也叫边沿触发。描述符上有数据就绪,如果用户把数据没有处理或没处理完,也只提醒一次,下一轮IO函数执行时不会提醒,除非有新数据到达。

一、LT模式

ltepoll.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>

//ltepoll
#define MAXFD 10

void epoll_add(int epfd, int fd)
{
    struct epoll_event ev;

   //ev.events = EPOLLIN;
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;

   if(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
    {
       perror("epoll ctl error");
   }


}

void epoll_del(int epfd, int fd)
{
    if(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) == -1)
    {
        perror("epoll ctl del error");
    }
}

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(sockfd != -1);

    struct sockaddr_in saddr, caddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
    assert(res != -1);

    listen(sockfd, 5);

    int epfd = epoll_create(MAXFD);

    epoll_add(epfd, sockfd);
    struct epoll_event events[MAXFD];

    while( 1 )
    {
        printf("epoll wait\n");
        int n = epoll_wait(epfd, events, MAXFD, 5000);
        if(n == -1)
        {
            printf("epoll_wait error\n");
            continue;
        }
        else if( n == 0 )
        {
            printf("time out\n");
            continue;
        }
        else
        {
            int i = 0;
            for(; i<n; i++)
            {
                int fd = events[i].data.fd;
                if(events[i].events & EPOLLIN)
                {
                    if(fd == sockfd)
                    {
                        int len = sizeof(caddr);
                        int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
                        printf("accept c = %d\n",c);
                       if(c < 0)
                        {
                            continue;
                        }
                        epoll_add(epfd, c);
                    }
                    else
                    {
                            char buff[128] = {0};
                            int num = recv(fd, buff, 1, 0);//127改为1
                            if(num <= 0)
                            {
                                epoll_del(epfd, fd);
                                close(fd);
                                printf("one client over\n");
                                break;
                            }
                            printf("recv(%d) = %s\n", fd, buff);
                            send(fd, "ok", 2, 0);
                        }
                    }
                }
            }
        }
    }

结果:

二、ET模式

etpoll.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>

#define MAXFD 10

//etepoll
void setnonblock(int fd)
{
    int oldfl = fcntl(fd, F_GETFL);
    int newfl = oldfl | O_NONBLOCK;
    if(fcntl(fd, F_SETFL, newfl) == -1)
    {
        perror("fcntl error");
    }
}

void epoll_add(int epfd, int fd)
{
    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;

    if(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
    {
        perror("epoll ctl error");
    }

    setnonblock(fd);
}

void epoll_del(int epfd, int fd)
{
    if(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) == -1)
    {
        perror("epoll ctl del error");
    }
}

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(sockfd != -1);

    struct sockaddr_in saddr, caddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
    assert(res != -1);

   listen(sockfd, 5);

   int epfd = epoll_create(MAXFD);

    epoll_add(epfd, sockfd);
    struct epoll_event events[MAXFD];

    while( 1 )
    {
        printf("epoll wait\n");
        int n = epoll_wait(epfd, events, MAXFD, 5000);
        if(n == -1)
        {
            printf("epoll_wait error\n");
            continue;
        }
        else if( n == 0 )
        {
            printf("time out\n");
            continue;
        }
        else
        {
            int i = 0;
            for(; i<n; i++)
            {
                int fd = events[i].data.fd;
                if(events[i].events & EPOLLIN)
                {
                    if(fd == sockfd)
                    {
                        int len = sizeof(caddr);
                        int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
                        printf("accept c = %d\n",c);

                        if(c < 0)
                        {
                            continue;
                        }
                        epoll_add(epfd, c);
                    }
                    else
                    {
                        while(1)
                        {
                            char buff[128] = {0};
                            int num = recv(fd, buff, 1 ,0);
                            if(num == -1)
                            {
                                if(errno == EAGAIN || errno == EWOULDBLOCK)
                                {
                                    send(fd, "ok", 2, 0);
                                }
                                break;
                            }
                            else if(num == 0)
                            {
                                epoll_del(epfd, fd);
                                close(fd);
                                printf("one client over\n");
                                break;
                            }
                            printf("recv(%d) = %s\n", fd, buff);
                        }
                    }
                }
            }
        }
    }
}

结果:

猜你喜欢

转载自blog.csdn.net/qq_41026740/article/details/83422775