linux网络编程(六)epoll反应堆

简介: linux网络编程(六)epoll反应堆

1.epoll反应堆(了解)


epoll反应堆建立思路:

1670952743398.jpg

#include <stdio.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MAX_EVENTS 1024
#define BUFLEN 4096
#define SERV_PORT 8080
void recvdata(int fd,int events ,void *arg);
void senddata(int fd,int events ,void *arg);
/*Describes information about the ready file descriptor */
struct myevents_s{
  int fd; //The file descriptor to listen 
  int events; //The corresponding listening event
  void *arg;//Generic type pointer
  void (*call_back)(int fd,int events,void *arg); //callback function
  int status;//1->listen 0-> stop to listen
  char buf[BUFLEN];
  int len;
  long last_active;//Record the time value of each addition of red-black tree "g_efd"
};
int g_efd;//A global variable that holds the file descriptor returned by "epoll_create"
struct myevent_s g_events[MAX_EVENTS+1];//+1--->listen fd
/*Initialize the structure "myevent_s"*/
//eventset(&g_events[MAX_EVENTS],lfd,acceptconn,&g_events[MAX_EVENTS]);
//void acceptconn(int lfd ,int events,void *arg)
void eventset(struct myevent_s *ev,int fd,void (*call_back)(int,int,void *),void *arg)
{
  ev->fd = fd;
  ev->call_back = call_back;
  ev->events = 0;
  ev->arg = arg;
  ev->status = 0;
  memset(ev->buf,0,sizeof(ev->buf));
  ev->len = 0;
  ev->last_active = time(NULL);
  return;
}
/*Adds a file descriptor to the red-black tree on which epoll listens */
//eventadd(efd,EPOLLIN,&g_events[MAX_EVENTS]);
void eventadd(int efd,int events,struct myevent_s *ev)
{
  struct epoll_event epv ={0,{0}};
  int op;
  epv.data.ptr =ev;
  epv.events = ev-> events = events;
  if(ev->status == 0){
  op = EPOLL_CTL_ADD;
  ev->status  = 1;
  }
  if(epoll_ctl(efd,op,e->fd,&epv)<0)
  printf("event add failed[fd = %d],events[%d]\n",ev->fd,events);
  else
  printf("event add OK [fd = %d],op= %d,events[%0X]\n",ev->fd,op,events);
  return;
}
// eventdel(g_efd,ev);
void eventdel(int efd,struct myevent_s *ev)
{
  struct epoll_event epv ={0,{0}};
  if(ev->status != 1)
  return ;
  //epv.data.ptr=NULL;
  epv.data.ptr = NULL;
  ev->status = 0;
  epoll_ctl(efd,EPOLL_CTL_DEL,ev->fd.&epv);
  return ;
}
void acceptconn(int lfd ,int events,void *arg)
{
  struct sockaddr_in cin; //client address
  socklen_t len = sizeof(cin);
  int cfd,i;
  if((cfd==accept(lfd,(struct sockaddr *)&cin,&len))==-1)
  {
  if(errno != EAGAIN && errno != EINTR)
  {
  /*not going to error handle it for now*/
  printf("%s:accept,%s\n",__func__,strerror(errno));
  return ;
  }
  do{
  for(i = 0;i < MAX_EVENTS;i++)//
    if(g_events[i].status == 0)//Find a free element from the global array g events
    break;
  if(i == MAX_EVENTS){
    printf("%s:max connect limit[%d]\n",__func__,MAX_EVENTS);
    break;
  }
  int flag = 0;
  if((flag = fcntl(cfd,F_SET,O_NONBLOCK))<0){  //cdf -->nonblocking
    printf("%s:fcntl nonblocking failed ,%s\n",__func__,strerror(errno));
    break;
  }
  eventset(&g_events[i],cfd,recvdata,&g_events[i]);
  eventadd(g_efd,EPOLLIN,&g_events[i]);
  }while(0);
  printf("new connect [%s:%d][time :%ld],pos[%d]\n",
    inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),g_events[i].last_active,i);
  return ;
}
}
/*create "socket", initlize "lfd" */
void initlistensocket(int efd,short port)
{
  struct sockaddr_in sin;
  int lfd = socket(AF_INET,SOCK_STREAM,0);
  fcntl(lfd,F_SETFL,O_NONBLOCK);//Set the socket to non-blocking
  memset(&sin,0,sizeof(sin));//bzero(&sin,sizeof(sin))
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_port = htons(port);
  bind(lfd,(struct sockaddr *)&sin,sizeof(sin));
  listen(lfd,20);
  /*void eventset(struct myevent_s *ev,int fd,void(*call_back)(int,int,void *),void *arg);*/
  eventset(&g_events[MAX_EVENTS],lfd,acceptconn,&g_events[MAX_EVENTS]);
  /*void eventadd(int efd,int eventsmstruct myevent_s *ev) */
  eventadd(efd,EPOLLIN,&g_events[MAX_EVENTS]);
  return ;
} 
//eventset(&g_events[i],cfd,recvdata,&g_events[i]);
void recvdata(int fd,int events,void *arg)
{
  struct myevent_s *ev = (struct myevent_s *)arg;
  int len;
  len = recv(fd,ev->buf,sizeof(ev->buf),0); //=read(),only use in network programming,setting flags == 0;
  eventdel(g_efd,ev);
  if(len > 0){
  ev->len = len;
  ev->buf[len]='\0';
  printf("C[%d]:%s\n",fd,ev->buf);
  eventset(ev,fd,senddata,ev);
  eventadd(g_efd,EPOLLOUT,ev);
  }else if(len == 0){
  close(ev->fd);
  printf("[fd=%d] pos[%ld],closed\n",fd,ev-g_events);
  }else{
  close(ev->fd);
  printf("recv[fd=%d] error[%d]:%s\n",fd,errno,strerror(errno));
  }
  return;
}
void senddata(int fd,int events,void *arg)
{
  struct myevent_s *ev=(struct myevent_s *)arg;
  int len;
  len = send(fd,ev->buf,ev->len,0);
  eventdel(g_efd,ev);
  if(len > 0){
  printf("send[fd = %d],[%d]%s\n",fd,len,ev->buf);
  eventset(ev,fd,recvdata,ev);
  eventadd(g_efd,EPOLLIN,ev);
  }else{
  close(ev->fd);
  printf("send[fd=%d] error %s\n",fd,strerror(errno));
  }
  return;
}
int main(int argc,char *argv[])
{
  unsigned short port = SERV_PORT; //Use the user-specified port. If no port is specified, use the default port
  if(argc == 2){
  port = atoi(argv[1]);
  }
  g_efd = epoll_create(MAX_EVENTS+1);//create the red black tree, return "g_efd"
  if(g_efd <= 0)
  printf("create efd in %s err %s\n",_func_ ,strerror(errno));
  initlistensocket(g_efd,port); //Initialize the listening socket
  struct epoll_event events[MAX_EVENTS+1];//Store an array of file descriptors that satisfy the ready events
  printf("server running : port[%d]\n",port);
  int checkpos = 0,i;
  while(1){
  /*1.Timeout verification. Test 100 links each time without testing listenfd. If the client has not communicated with the server within 60 seconds, close the client link*/
  long now = time(NULL);//present time
  for(i = 0;i<100;i++,checkpos++){//Check 100 at a time and use checkpos to control the check objects
    if(checkpos == MAX_EVENTS)
    checkpos = 0;
    if(g_events[checkpos].status != 1)//Not on the red-black tree "g_efd"
    continue;
  long duration = now - g_events[checkpos].last_active;//Time when the client is inactive
  if(duration >= 60){
    close(g_events[checkpos].fd);//Close the link with the client
    printf("[fd=%d] timeout\n",g_events[checkpos].fd);
    eventdel(g_efd,&g_events[checkpos]);//Remove the client from the red black tree "g_efd"
    }
  }
  /*2.Listen to the red-black tree "g_efd" and add the described file descriptor  to the events array. If no event is satisfied for 1 second, return 0*/
  int nfd =epoll_wait(g_efd,events,MAX_EVENTS+1,1000);//timeout = 1000
  if(nfd < 0){
    printf("epoll_wait error,exit\n");
    break;
  }
   for(i=0;i<nfd;i++){
    /* Accepts void *ptr members of the union data using a custom struct pointer of type myevent_s */
    struct myevent_s *ev = (struct myevent_s *)events[i].data.ptr;
    if((events[i].events & EPOLLIN)&&(ev -> events & EPOLLIN)){ //Read ready event
      ev->call_back(ev->fd,events[i].events,ev->arg);
    }
    if((events[i].events&EPOLLOUT)&&(ev->events & EPOLLOUT)){ //write ready event
      ev->call_back(ev->fd,events[i].events,ev->arg);
    }
   }
  }
  return 0;
}
相关文章
|
19天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
43 6
|
19天前
|
网络协议 Linux Python
Python网络编程基础(Socket编程)epoll在Linux下的使用
【4月更文挑战第12天】在上一节中,我们介绍了使用`select`模块来实现非阻塞IO的方法。然而,`select`模块在处理大量并发连接时可能会存在性能问题。在Linux系统中,`epoll`机制提供了更高效的IO多路复用方式,能够更好地处理大量并发连接。
|
10天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
2天前
|
安全 网络协议 Linux
【专栏】一文教你玩转 Linux 的 ping 命令,从此成为 Linux 网络高手
【4月更文挑战第28天】本文详细介绍了Linux系统中ping命令的使用,包括其基本语法、输出信息、常用参数及高级用法。通过ping,用户可测试网络连通性、诊断故障及评估性能。此外,文章还讨论了ping在不同协议、模拟网络环境及与其他命令结合使用时的场景。注意防火墙和网络环境可能影响ping结果,理解错误信息有助于网络问题排查。熟练掌握ping命令,能助你成为Linux网络专家。不断学习和实践,提升网络技能,为构建稳定网络环境贡献力量。
|
4天前
|
运维 网络协议 Linux
【Linux】CentOS网络故障排查大揭秘: 实战攻略解读
【Linux】CentOS网络故障排查大揭秘: 实战攻略解读
|
7天前
|
网络协议 Linux Shell
【linux网络(一)】初识网络, 理解四层网络模型
【linux网络(一)】初识网络, 理解四层网络模型
|
7天前
|
安全 Ubuntu Linux
Linux 网络操作命令Telnet
Linux 网络操作命令Telnet
23 0
Linux 网络操作命令Telnet
|
8天前
|
Ubuntu Linux
Linux(22) Linux设置网络优先级顺序
Linux(22) Linux设置网络优先级顺序
8 0
|
8天前
|
Ubuntu 网络协议 Linux
Linux(20) Ubuntu 20.04 网络接口自动切换路由配置
Linux(20) Ubuntu 20.04 网络接口自动切换路由配置
32 0
|
2月前
|
网络协议 算法 Java