udp epoll tcp epoll使用

来源:互联网 发布:网络水晶头哪个牌子好 编辑:程序博客网 时间:2024/05/21 05:06


udp epoll

#define _GNU_SOURCE 1



#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>


#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>


#define ADDR  INADDR_LOOPBACK
#define PORT  34567


#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))


#define SAVE_ERRNO(block) do { int errno_ = errno; { block; } errno = errno_; } while (0)


typedef struct {
  int fd;
  unsigned int readable:1;
  unsigned int writable:1;
} peer_t;


static int tmfd = -1;
static int epfd = -1;
static int npeers;


static unsigned long bytes_read;
static unsigned long bytes_written;




static void do_report(void) {
  printf(
    "=====================\n"
    "%lu bytes read\n"
    "%lu bytes written\n",
    bytes_read, bytes_written);


  bytes_read = 0;
  bytes_written = 0;
}




static int do_close(int fd) {
  int r;


  do
    r = close(fd);
  while (r == -1 && errno == EINTR);


  return r;
}




static int add_fd(int fd, void *arg, int events) {
  struct epoll_event ee = { .data.ptr = arg, .events = events | EPOLLET };
  return epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ee);
}




static int make_sock_fd(unsigned short port) {
  struct sockaddr_in sin;
  int sockfd;


  if ((sockfd = socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0)) == -1)
    return -1;


  memset(&sin, 0, sizeof sin);
  sin.sin_addr.s_addr = htonl(ADDR);
  sin.sin_port = htons(port);
  sin.sin_family = AF_INET;


  if (bind(sockfd, (struct sockaddr *) &sin, sizeof sin) == -1)
    return -1;


  return sockfd;
}




static int make_timer_fd(unsigned int ms) {
  struct itimerspec its;


  if ((tmfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) == -1)
    return -1;


#define SET_TS(ts, ms) ((ts)->tv_sec = (ms) / 1000, (ts)->tv_nsec = ((ms) % 1000) * 1e6)
  SET_TS(&its.it_interval, ms);
  SET_TS(&its.it_value, ms);


  if (timerfd_settime(tmfd, 0, &its, NULL)) {
    SAVE_ERRNO(do_close(tmfd));
    return -1;
  }


  return tmfd;
}




static int do_recv(int fd) {
  char buf[1024];
  ssize_t r;


  do
    r = read(fd, buf, sizeof buf);
  while (r == -1 && errno == EINTR);


  if (r > 0)
    bytes_read += r;


  return r;
}




static int do_send(int fd, const void *data, size_t size) {
  struct sockaddr_in sin;
  ssize_t r;


  static int port = PORT;
  port = PORT + (((port - PORT) + 1) % npeers);


  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(ADDR);
  sin.sin_port = htons(port);


  do
    r = sendto(fd, data, size, 0, (struct sockaddr *) &sin, sizeof sin);
  while (r == -1 && errno == EINTR);


  if (r > 0)
    bytes_written += r;


  return r;
}




static int do_epoll(void) {
  struct epoll_event out[1024];
  peer_t *peer;
  int i, n, r;
  int events;
  int fd;


  do
    n = epoll_wait(epfd, out, ARRAY_SIZE(out), -1);
  while (n == -1 && errno == EINTR);


  if (n == -1)
    return -1;


  for (i = 0; i < n; i++) {
    events = out[i].events;
    peer = out[i].data.ptr;
    fd = peer->fd;


    if (events & ~(EPOLLIN|EPOLLOUT))
      return -1;


    if (fd == tmfd) {
      char buf[8];
      read(fd, buf, 8);
      do_report();
      continue;
    }


    if (peer->readable && (events & EPOLLIN)) {
      if ((r = do_recv(fd)) == -1)
        return -1;
      else
        peer->readable = 0, peer->writable = 1;
    }


    if (peer->writable  && (events & EPOLLOUT)) {
      const char reply[] = "PING";


      if ((r = do_send(fd, reply, sizeof(reply) - 1)) == -1)
        return -1;
      else
        peer->readable = 1, peer->writable = 0;
    }
  }


  return 0;
}




int main(int argc, char **argv) {
  peer_t *peers;
  peer_t tmp;
  int i, r;


  (void) argc;


  if (argv[1] == NULL || (npeers = atoi(argv[1])) == 0)
    npeers = 100;


  if ((epfd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
    perror("make_epoll_fd");
    exit(1);
  }


  if ((tmfd = make_timer_fd(2000)) == -1) {
    perror("make_timer_fd");
    exit(1);
  }


  tmp.fd = tmfd;
  if (add_fd(tmfd, &tmp, EPOLLIN)) {
    perror("add_fd");
    exit(1);
  }


  if ((peers = calloc(npeers, sizeof(peers[0]))) == NULL) {
    perror("malloc");
    exit(1);
  }


  for (i = 0; i < npeers; i++) {
    peers[i].readable = 0;
    peers[i].writable = 1;
    if ((peers[i].fd = make_sock_fd(PORT + i)) == -1)
      perror("make_sock_fd");
    else if (add_fd(peers[i].fd, &peers[i], EPOLLIN|EPOLLOUT))
      perror("add_fd");
  }


  while ((r = do_epoll()) == 0)
    /* nop */ ;


  if (r == -1) {
    perror("do_epoll");
    exit(1);
  }


  return 0;

}




0 0
原创粉丝点击