Advertisement
Guest User

epoll_writev_4threads

a guest
Jun 17th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.90 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <errno.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <pthread.h>
  8. #include <sys/uio.h>
  9. #include <arpa/inet.h>
  10. #include <sys/mman.h>
  11. #include <sys/epoll.h>
  12. #include <sys/socket.h>
  13. #include <netinet/in.h>
  14. #include <netinet/tcp.h>
  15.  
  16. #define THREADS 4
  17. #define PORT 12345
  18.  
  19. #define NUM_EVENTS 128
  20. #define NUM_RESPONSES 128
  21. #define READ_BUFFER_SIZE (32 * 1024)
  22. #define HTTP_RESPONSE "HTTP/1.1 200 Ok\r\nContent-Length: 11\r\n\r\nHello World"
  23.  
  24. static struct iovec responses[NUM_RESPONSES];
  25.  
  26. int find_clrf(const char* buffer, int len) {
  27.     const unsigned int CLRF = '\r' | ('\n' << 8) | ('\r' << 16) | ('\n' << 24);
  28.     int offset = 0;
  29.     while (len >= sizeof(unsigned int)) {
  30.         if (*((unsigned int*) &buffer[offset]) == CLRF)
  31.             return offset + 4;
  32.         offset++;
  33.         len--;
  34.     }
  35.     return -1;
  36. }
  37.  
  38. void* worker(void* arg) {
  39.     int client;
  40.     struct epoll_event event;
  41.     char buffer[READ_BUFFER_SIZE];
  42.  
  43.     int epoll = ((int*) arg)[0];
  44.     int server = ((int*) arg)[1];
  45.     struct epoll_event events[NUM_EVENTS];
  46.  
  47.     while (1) {
  48.         int n = epoll_wait(epoll, events, NUM_EVENTS, -1);
  49.         while (n--) {
  50.             struct epoll_event* ev = &events[n];
  51.             if (ev->events & (EPOLLERR | EPOLLHUP)) {
  52.                 close(ev->data.fd);
  53.  
  54.             } else if (ev->data.fd == server) {
  55.                 while ((client = accept4(server, NULL, NULL, SOCK_NONBLOCK)) != -1) {
  56.                     int enable = 1;
  57.                     setsockopt(client, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
  58.                     event.data.fd = client;
  59.                     event.events = EPOLLIN | EPOLLONESHOT;
  60.                     epoll_ctl(epoll, EPOLL_CTL_ADD, client, &event);
  61.                 }
  62.                 event.data.fd = server;
  63.                 event.events = EPOLLIN | EPOLLONESHOT;
  64.                 epoll_ctl(epoll, EPOLL_CTL_MOD, server, &event);
  65.  
  66.             } else {
  67.                 int buf_len, offset = 0, num_requests = 0;
  68.                 while ((buf_len = read(ev->data.fd, buffer + offset, READ_BUFFER_SIZE)) > 0) {
  69.                     int clrf_offset = 0;
  70.                     while ((clrf_offset = find_clrf(buffer + clrf_offset + offset, buf_len)) != -1)
  71.                         num_requests++;
  72.                     offset += buf_len;
  73.                 }
  74.  
  75.                 writev(ev->data.fd, responses, num_requests);
  76.                 if (offset == 0 || (buf_len <= 0 && errno != EAGAIN)) {
  77.                     close(ev->data.fd);
  78.                 } else {
  79.                     event.data.fd = ev->data.fd;
  80.                     event.events = EPOLLIN | EPOLLONESHOT;
  81.                     epoll_ctl(epoll, EPOLL_CTL_MOD, event.data.fd, &event);
  82.                 }
  83.             }
  84.         }
  85.     }
  86.  
  87.     return NULL;
  88. }
  89.  
  90. int main() {
  91.     struct sockaddr_in server_addr;
  92.     server_addr.sin_family = AF_INET;
  93.     server_addr.sin_port = htons(PORT);
  94.     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  95.  
  96.     int server = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
  97.     bind(server, (struct sockaddr*)&server_addr, sizeof(server_addr));
  98.     listen(server, SOMAXCONN);
  99.  
  100.     struct epoll_event event;
  101.     event.data.fd = server;
  102.     event.events = EPOLLIN | EPOLLONESHOT;
  103.     int epoll = epoll_create1(0);
  104.     epoll_ctl(epoll, EPOLL_CTL_ADD, server, &event);
  105.  
  106.     for (int i = 0; i < NUM_RESPONSES; i++) {
  107.         responses[i].iov_base = HTTP_RESPONSE;
  108.         responses[i].iov_len = sizeof(HTTP_RESPONSE) - 1;
  109.     }
  110.  
  111.     pthread_t thread;
  112.     cpu_set_t cpuset;
  113.     int fds[2] = { epoll, server };
  114.     for (int i = 0; i < THREADS - 1; i++) {
  115.         CPU_ZERO(&cpuset);
  116.         CPU_SET(i, &cpuset);
  117.         pthread_create(&thread, NULL, worker, &fds);
  118.         //pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
  119.     }
  120.  
  121.     printf("Listener staretd on :%d\n", PORT);
  122.     worker(&fds);
  123. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement