Last active
May 8, 2017 14:21
-
-
Save justdoit0823/93e81ccf7bf3c3e464ccf96d2013b88a 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
#include "stdio.h" | |
#include "unistd.h" | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <errno.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <pthread.h> | |
#include <sys/epoll.h> | |
#include <fcntl.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#define MAX_EVENTS 10 | |
int setnonblocking(int fd){ | |
int flag, ret; | |
flag = fcntl(fd, F_GETFL, NULL); | |
flag |= O_NONBLOCK; | |
ret = fcntl(fd, F_SETFL, flag); | |
return ret; | |
} | |
int start_listen_server(const char * host, int port){ | |
int s_sock, flag; | |
struct sockaddr_in addr; | |
printf("host %s, port %d\n", host, port); | |
memset(&addr, 0, sizeof(addr)); | |
inet_aton(host, &addr.sin_addr); | |
addr.sin_family = AF_INET; | |
addr.sin_port = htons(port); | |
s_sock = socket(AF_INET, SOCK_STREAM, 0); | |
flag = 1; | |
setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); | |
setnonblocking(s_sock); | |
bind(s_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)); | |
listen(s_sock, 5); | |
return s_sock; | |
} | |
const char * get_instance_name(int thread_mode){ | |
return thread_mode ? "thread": "process"; | |
} | |
void * poll_loop(void * args){ | |
int nfds, conn_sock, listen_sock, addrlen, id, thread_mode; | |
struct sockaddr_in addr; | |
struct epoll_event ev, events[MAX_EVENTS]; | |
int epollfd, et_mode; | |
listen_sock = ((int *)args)[0]; | |
thread_mode = ((int *)args)[1]; | |
et_mode = ((int *)args)[2]; | |
printf("sock %d, thread_mode %d, et mode %d.\n", listen_sock, thread_mode, et_mode); | |
if(thread_mode == 1) id = pthread_self(); | |
else id = getpid(); | |
printf("run in %s %d.\n", get_instance_name(thread_mode), id); | |
epollfd = epoll_create1(0); | |
if (epollfd == -1) { | |
printf("epoll_create1\n"); | |
exit(1); | |
} | |
ev.events = EPOLLIN; | |
if(et_mode) ev.events |= EPOLLET; | |
ev.data.fd = listen_sock; | |
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) { | |
printf("epoll_ctl: listen_sock\n"); | |
exit(1); | |
} | |
while(1){ | |
printf("epoll wait in %s %u.\n", get_instance_name(thread_mode), id); | |
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); | |
printf("finish waiting with %d fds in %s %u.\n", nfds, get_instance_name(thread_mode), id); | |
if (nfds == -1) { | |
printf("epoll_wait error\n"); | |
break; | |
} | |
while(1){ | |
conn_sock = accept(listen_sock, (struct sockaddr *) &addr, &addrlen); | |
if(conn_sock == -1) { | |
if(errno == EAGAIN || errno == EWOULDBLOCK){ | |
printf("accept failure in %s %u\n", get_instance_name(thread_mode), id); | |
break; | |
} | |
} | |
else if(conn_sock > 0){ | |
printf("accept succes %s %u\n", get_instance_name(thread_mode), id); | |
} | |
} | |
} | |
printf("run in %s %u.\n", get_instance_name(thread_mode), id); | |
} | |
int run_thread_server(int argc, char * argv[]){ | |
int server_sock, et_mode; | |
pthread_t threads[2]; | |
int args[2]; | |
if(argc > 4) et_mode = atoi(argv[4]); | |
else et_mode = 0; | |
server_sock = start_listen_server(argv[2], atoi(argv[3])); | |
args[0] = server_sock; | |
args[1] = 1; | |
args[2] = et_mode; | |
pthread_create(&threads[0], NULL, poll_loop, &args[0]); | |
pthread_create(&threads[1], NULL, poll_loop, &args[0]); | |
pthread_join(threads[0], NULL); | |
pthread_join(threads[1], NULL); | |
return 0; | |
} | |
int run_server(int argc, char * argv[]){ | |
int server_sock, et_mode, pid; | |
int args[2]; | |
if(argc > 4) et_mode = atoi(argv[4]); | |
else et_mode = 0; | |
server_sock = start_listen_server(argv[2], atoi(argv[3])); | |
pid = fork(); | |
if(pid == -1){ | |
printf("fork error.\n"); | |
exit(0); | |
} | |
args[0] = server_sock; | |
args[1] = 0; | |
args[2] = et_mode; | |
if(pid == 0){ | |
poll_loop(&args[0]); | |
} | |
else{ | |
poll_loop(&args[0]); | |
waitpid(pid, NULL, 0); | |
} | |
return 0; | |
} | |
int main(int argc, char * argv[]){ | |
if(strcmp(argv[1], "thread") == 0) run_thread_server(argc, argv); | |
else run_server(argc, argv); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment