I/O多路转接(三)——epoll函数

I/O多路转接(三)——epoll函数

第三篇介绍epoll函数。
介绍先略过,还在整理当中,先贴代码。

使用epoll LT与ET模式的网路服务器

LT
这是一个简单的服务器,三次握手后只完成一次读写就关闭连接。通过浏览器发送一个HTTP请求,服务器传回HELLO EPOLL消息。
server.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/epoll.h>

const char *msg = "HTTP/1.1 200 OK\r\n\r\n<html><h1>Hello epoll!</h1></html>";
int startup(char*ip,int port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket");
        return 2;
    }
    int opt = 1;
    setsockopt(sock, SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = inet_addr(ip);
    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
        perror("bind");
        return 3;
    }

    if(listen(sock,10) < 0){
        perror("listen");
        return 4;
    }
    return sock;
}

int main(int argc,char *argv[])
{
    if(argc!= 3){
        printf("Usage:%s [ip] [port]\n",argv[0]);
        return 1;
    }
    int listen_sock = startup(argv[1],atoi(argv[2]));
    printf("listen_sock has been created,the value is %d\n",listen_sock);
    //监听套接字创建完成.

    int epfd = epoll_create(256);//创建epoll模型,返回一个epoll模型句柄。
    if(epfd < 0){
        perror("epoll_create");
        return 5;
    }
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = listen_sock;
    epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev);//将listen_sock添加到rb_tree;
    int nums = -1;
    int timeout = 1000;
    struct epoll_event revs[64];//epoll事件集
    int size = 64;
    while(1){
        nums = epoll_wait(epfd,revs,size,-1);
        switch(nums){
            case 0:
                printf("timeout\n");
                break;
            case -1:
                perror("epoll_wait");
                break;
            default:
                {
                    //已经有事件就绪。
                    int i= 0;
                    for(;i < nums;i++){
                        int fd = revs[i].data.fd;
                        if(fd==listen_sock&&revs[i].events&EPOLLIN{
                        //listen_sock读事件已经就绪。
                            struct sockaddr_in client;
                            socklen_t len = sizeof(client);
                            int new_sock = accept(listen_sock,(struct sockaddr*)&client,&len);
                            if(new_sock < 0){
                                perror("accept");
                                continue;
                            }
                                printf("get a client!ip:%s,port:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
                                //将CLIENT的socket添加到epoll中
                                ev.events = EPOLLIN;
                                ev.data.fd = new_sock;
                                epoll_ctl(epfd,EPOLL_CTL_ADD,new_sock,&ev);
                        }else if(fd!= listen_sock){//其他关心描述符状态改变。
                            if(revs[i].events&EPOLLIN){
                                char buf[4096];
                                ssize_t s = read(fd,buf,sizeof(buf)-1);
                                if(s >0){
                                    buf[s]= 0;
                                    printf("client say# %s\n",buf);
                                    ev.events = EPOLLOUT;//读后关心这个fd的写事件。
                                    ev.data.fd = fd;
                                    epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&ev);

                                }else if(s==0){
                                    printf("client is quit!\n");
                                    close(fd);
                                    epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
                                }else{
                                    perror("read");
                                    close(fd);
                                    epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
                                }
                            }else if(revs[i].events&EPOLLOUT){
                                write(fd,msg,strlen(msg));
                                close(fd);
                                epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
                            }
                        }
                    } 
                }
                break; 
        }
    }

使用epoll ET模式的网路服务器

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

const char *msg = "HTTP/1.1 200 OK\r\n\r\n<html><h1>Hello epoll!</h1></html>";
struct epoll_event ev;
#define SIZE 64
typedef struct fd_buff{
    int fd;
    char buf[SIZE];
    int size;
}fdbuff,*fdbuff_p;

void* alloc_buff(int fd)
{
    fdbuff_p tmp =(fdbuff_p)malloc(sizeof(fdbuff));
    if(!tmp){
        perror("malloc");
        return NULL;
    }
    tmp->fd = fd;
    tmp->size = SIZE;
    return tmp;
}
int startup(char*ip,int port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket");
        return 2;
    }
    int opt = 1;
    setsockopt(sock, SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = inet_addr(ip);
    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
        perror("bind");
        return 3;
    }

    if(listen(sock,10) < 0){
        perror("listen");
        return 4;
    }
    return sock;
}

 void set_nonblock(int fd)//设置套接字为非阻塞。
{
    int fl = fcntl(fd, F_GETFL);//拿到当前套接字状态保存到fl
    fcntl(fd,F_SETFL,fl|O_NONBLOCK);//设置为非阻塞态
}

int myread(int fd, char buf[],int size)
{
    ssize_t len = 0;
    ssize_t total = 0;
    int count = 0;
    while((len = read(fd,buf+total,100))> 0){
        count++;
        total += len;
        printf("read %d!msg:%s total = %d\n",count,buf,total);
    }
    if(len < 0||errno== EAGAIN)
        printf("read done! total = %d\n",total);
    else if(len==0)
        return 0;
    else
        return -1;
    return total;
}

int mywrite(int fd, char buf[],int size)
{
    ssize_t len = 0;
    ssize_t total = 0;
    int count = 0;
    while(1){
        len = write(fd,buf+total,strlen(buf+total));
        if(len > 0)
            total += len;
        if(len < 0||errno== EAGAIN){
                printf("write done! total = %d\n",total);
                break;
        }

    }
    return total;
}

int myaccept(int listen_sock,int epfd)
{
    struct sockaddr_in client;
    socklen_t len = sizeof(client);
    int new_sock = 0;
    int count = 0;
    while(( new_sock = accept(listen_sock,(struct sockaddr*)&client,&len))>0){
        count++;
        printf("get a client!ip:%s,port:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
        //将CLIENT的socket添加到epoll中
        ev.events = EPOLLIN|EPOLLET;
        set_nonblock(new_sock);
        ev.data.ptr = alloc_buff(new_sock);
        epoll_ctl(epfd,EPOLL_CTL_ADD,new_sock,&ev);
    }
    if(new_sock < 0&&errno==EAGAIN){
        printf("server has accept all client,count= %d\n",count);
    }
}

void del_buff(fdbuff_p p)
{
    if(p!=NULL)
        free(p);
}

int main(int argc,char *argv[])
{
    if(argc!= 3){
        printf("Usage:%s [ip] [port]\n",argv[0]);
        return 1;
    }
    int listen_sock = startup(argv[1],atoi(argv[2]));
    set_nonblock(listen_sock);
    printf("listen_sock has been created,the value is %d\n",listen_sock);
    //监听套接字创建完成.

    int epfd = epoll_create(256);//创建epoll模型,返回一个epoll模型句柄。
    if(epfd < 0){
        perror("epoll_create");
        return 5;
    }
    ev.events = EPOLLIN|EPOLLET;
    ev.data.ptr =alloc_buff(listen_sock);
    epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev);//将listen_sock添加到rb_tree;
    int nums = -1;
    int timeout = 1000;
    struct epoll_event revs[64];//epoll事件集
    int size = 64;
    while(1){
        nums = epoll_wait(epfd,revs,size,-1);
        switch(nums){
            case 0:
                printf("timeout\n");
                break;
            case -1:
                perror("epoll_wait");
                break;
            default:
                {
                    //已经有事件就绪。
                    int i= 0;
                    for(;i < nums;i++){
                        fdbuff_p fp =(fdbuff_p)revs[i].data.ptr;
                        if(fp->fd == listen_sock&&revs[i].events&EPOLLIN ){//listen_sock读事件已经就绪。
                            myaccept(listen_sock, epfd);

                        }else if(fp->fd!= listen_sock){//其他关心描述符状态改变。
                            if(revs[i].events&EPOLLIN){
                                ssize_t s = myread(fp->fd,fp->buf,fp->size);
                                if(s >0){
                                    fp->buf[s]=0;
                                    printf("client say# %s\n",fp->buf);
                                    ev.events = EPOLLOUT|EPOLLET;//读后关心这个fd的写事件。
                                    ev.data.ptr = fp;
                                    epoll_ctl(epfd,EPOLL_CTL_MOD,fp->fd,&ev);

                                }else if(s==0){
                                    printf("client is quit!\n");
                                    close(fp->fd);
                                    epoll_ctl(epfd,EPOLL_CTL_DEL,fp->fd,NULL);
                                    del_buff(fp);
                                }else{
                                    perror("read");
                                    close(fp->fd);
                                    epoll_ctl(epfd,EPOLL_CTL_DEL,fp->fd,NULL);
                                    del_buff(fp);
                                }
                            }else if(revs[i].events&EPOLLOUT){
                                mywrite(fp->fd,fp->buf,fp->size);
                                close(fp->fd);
                                epoll_ctl(epfd,EPOLL_CTL_DEL,fp->fd,NULL);
                                //del_buff(fp);
                            }
                        }
                    } 
                }
                break; 
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值