Created
August 13, 2010 23:38
-
-
Save punytan/523728 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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