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;
}
相关文章
|
6月前
|
安全 Linux 网络安全
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
189 0
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
|
7月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
478 18
|
7月前
|
网络协议 关系型数据库 Linux
【App Service Linux】在Linux App Service中安装 tcpdump 并抓取网络包
在App Service for Linux环境中,无法像Windows一样直接使用网络排查工具抓包。本文介绍了如何通过TCPDUMP在Linux环境下抓取网络包,包括SSH进入容器、安装tcpdump、执行抓包命令及下载分析文件的完整操作步骤。
367 5
|
8月前
|
Web App开发 网络协议 Linux
【Linux】网络基础
TCP/IP五层模型是网络通信的基础框架,将复杂的数据传输过程分为物理层、数据链路层、网络层、传输层和应用层,每层各司其职,协同完成远程通信。该模型确保了不同设备和网络之间的互联互通,是现代互联网运行的核心机制。
800 5
|
10月前
|
安全 网络协议 Linux
Linux网络应用层协议展示:HTTP与HTTPS
此外,必须注意,从HTTP迁移到HTTPS是一项重要且必要的任务,因为这不仅关乎用户信息的安全,也有利于你的网站评级和粉丝的信心。在网络世界中,信息的安全就是一切,选择HTTPS,让您的网站更加安全,使您的用户满意,也使您感到满意。
289 18
|
8月前
|
网络协议 Linux 开发者
深入Linux中UDP网络通信机制编程探索
以上步骤概述了Linux中UDP网络通信的编程机制。在实现时,因关注细节和上下文环境可能有所调整,但大致流程是一致的。这些知识片段旨在帮助开发者快速上手Linux下的UDP编程,并提供可靠的信息作为编程的基础。在编程实践中,应结合实际业务需求,设计合适的数据传输协议,确保数据的正确性和实时性。
199 0
|
10月前
|
Linux 数据安全/隐私保护
使用Linux命令行接入无线网络Wi-Fi的示例。
现在,你已经使用命令行成功地连接到 Wi-Fi 网络了。这两个示例涵盖了用 `nmcli` 和 `wpa_supplicant` 连接无线网络的常见场景,让你能够不依赖图形化界面来完成这个任务。在日常使用中熟练掌握这些基本操作能增强你对 Linux 系统的理解,帮助你更有效地处理各种问题。
812 12
|
10月前
|
安全 Ubuntu Linux
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
415 0
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
|
12月前
|
Ubuntu Linux
Linux系统管理:服务器时间与网络时间同步技巧。
以上就是在Linux服务器上设置时间同步的方式。然而,要正确运用这些知识,需要理解其背后的工作原理:服务器根据网络中的其他机器的时间进行校对,逐步地精确自己的系统时间,就像一只犹豫不决的啮齿动物,通过观察其他啮齿动物的行为,逐渐确定自己的行为逻辑,既简单,又有趣。最后希望这个过程既能给你带来乐趣,也能提高你作为系统管理员的专业素养。
1941 20
|
12月前
|
JSON 运维 Ubuntu
Linux下如何使用Curl进行网络请求
希望这篇文章能帮助您在Linux下更好地使用Curl进行网络请求。如有疑问,请随时提问!
663 10