当前位置: 代码迷 >> 综合 >> 2022-3-4
  详细解决方案

2022-3-4

热度:36   发布时间:2023-10-14 11:25:24.0

2022-3-4

  • epoll
    • 实现多路IO转接
    • 边沿触发和水平触发

epoll

实现多路IO转接

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<ctype.h>int main((int argc, char *argv[]){
    int i,n,j;int listenfd,connfd,efd,res,nready;struct epoll_event tep,ep[OPEN_MAX];char buf[BUFSIZ];struct sockaddr_in clie_addr, serv_addr;socklen_t clie_addr_len;listenfd = socket(AF_INET, SOCK_STREAM, 0);int opt=1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port= htons(9527);bind(listenfd, (struct sockaddr *) serv_addr, sizeof(serv_addr));listen(listenfd,128);efd = epoll_creat(OPEN_MAX);if(efd==-1)perr_exit("creat erro");tep.event = EPOLLIN;tep.data.fd = listenfd;res=epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &tep);if(res==-1)perr_exit("epoll_ctl erro");while(1){
    nready = epoll_wait(efd, &ep, OPEN_MAX, -1);if(nready == -1)perr_exit("epoll_wait erro");for(i=0;i<nready;++i){
    if(!ep[i]&EPOLLIN)continue;if(ep[i].data.fd==listenfd){
    clie_addr_len = sizeof(clie_addr);connfd = accept(listenfd, (struct sockaddr *) clie_addr, clie_addr_len)tep.event = EPOLLIN;tep.data.fd= connfd;res = epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &tep);continue;}n = read(ep[i].data.fd, buf, sizeof(buf));if(n==0){
    res = epoll_ctl(efd, EPOLL_CTL_DEL, ep[i].data.fd, NULL);close(ep[i].data.fd);}for(j=0;j<sizeof(buf);++j){
    buf[j]=toupper(buf[j]);}write(ep[i], buf, n);}}
}

边沿触发和水平触发

就是模电里的知识,epoll默认是水平触发,也就是只要还有消息就会触发epoll_wait,边沿触发是有消息来才进行一次触发
2022-3-4
如上图,管道内子程序写东西,一次写了10字节,“aaaa\nbbbb\n”,但是父进程读的时候一次读5个,也就是第一次读“aaaa\n”,这时管道内还有bbbb\n存在,如果是水平触发的话,读完第一次“aaaa\n”后,重新进行while循环的时候还是会触发epoll_wait,进行第二次读取,如果是边沿触发则不会在第二次while循环的时候读取了,直到子程序向管道内写入新的东西的时候才会读取bbbb\n