Skip to content

Instantly share code, notes, and snippets.

@punytan
Created August 13, 2010 23:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save punytan/523728 to your computer and use it in GitHub Desktop.
Save punytan/523728 to your computer and use it in GitHub Desktop.
/*
* epoll_sample.c
*
* forked from http://d.hatena.ne.jp/odz/20070507/1178558340
*
* compile : gcc -O3 -o epoll_sample epoll_sample.c
* bench : ab -n 10000 -c 50 http://localhost:8080/
*
* fix me :)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT "8080" /* must be _string_ */
#define MAX_EVENTS 100
#define BACKLOG 10
static int listener;
static int epfd;
static void die (const char* msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
static void setnonblocking(int sock)
{
int flag = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flag | O_NONBLOCK);
}
static int setup_socket()
{
int sock;
struct addrinfo *res, hints;
int optval = 1;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
if ((getaddrinfo(NULL, SERVER_PORT, &hints, &res) != 0))
die("getaddrinfo");
if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0)
die("socket");
if ((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(optval))) < 0)
die("setsockopt");
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
die("bind");
if (listen(sock, BACKLOG) < 0)
die("listen");
freeaddrinfo(res);
return sock;
}
int main()
{
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
char buffer[1024];
char res[2048];
snprintf(res, sizeof(res),
"HTTP/1.0 200 OK\r\n"
"Content-Lnegth: 7\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"HELLO\r\n");
if ((epfd = epoll_create(MAX_EVENTS)) < 0)
die ("epoll_create");
listener = setup_socket();
memset(&ev, 0, sizeof(ev));
ev.events = EPOLLIN;
ev.data.fd = listener;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev) < 0)
die("epoll set insertion error");
int i, nfd;
while (1) {
nfd = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (i = 0; i < nfd; i++) {
if (events[i].data.fd == listener) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client = accept(listener, (struct sockaddr *)&client_addr, &client_addr_len);
if (client < 0) {
perror("accept");
continue;
}
setnonblocking(client);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = client;
if(epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev) < 0)
die("epoll set insertion error");
} else {
int client = events[i].data.fd;
int n = read(client, buffer, sizeof(buffer));
if (n < 0) {
perror("read");
if (epoll_ctl(epfd, EPOLL_CTL_DEL, client, &ev) < 0)
perror("epoll delete error");
} else if (n == 0) {
if (epoll_ctl(epfd, EPOLL_CTL_DEL, client, &ev) < 0)
perror("epoll delete error");
} else {
write(client, res, (int)strlen(res));
if (epoll_ctl(epfd, EPOLL_CTL_DEL, client, &ev) < 0)
perror("epoll delete error");
}
shutdown(client, SHUT_RDWR);
close(client);
}
}
}
close(epfd);
close(listener);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment