Skip to content

Instantly share code, notes, and snippets.

@NicolasT
Created February 7, 2017 01:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NicolasT/3375707671eaa1ae0e00b9cc5ba855d3 to your computer and use it in GitHub Desktop.
Save NicolasT/3375707671eaa1ae0e00b9cc5ba855d3 to your computer and use it in GitHub Desktop.
/*
* $ make testepoll CFLAGS="-Wall -Werror -ggdb3"
*
* One console:
*
* $ nc -l 8000
*
* Other console:
*
* $ ./testepoll
*
* Then when requested, kill the `nc`, check socket status
*
* $ netstat -atnpl | grep 8000
*
* which should show `CLOSE_WAIT`, and press return in the `testepoll` console
*/
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
static int do_epoll(int epoll) {
int rc = -1,
i = 0;
struct epoll_event events[2] = { 0 };
rc = epoll_wait(epoll, events, sizeof(events) / sizeof(events[0]), -1);
if(rc == -1) {
return -1;
}
for(i = 0; i < rc; i++) {
printf("event: %d, fd: %d\n", events[i].events, events[i].data.fd);
}
return 0;
}
int main(int argc, char **argv) {
int epoll = -1,
rc = 1,
sock = -1,
i = 0;
struct addrinfo hints = { 0 },
*result = NULL,
*rp = NULL;
struct epoll_event event = { 0 };
char buf[16] = { 0 };
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
rc = getaddrinfo("localhost", "8000", &hints, &result);
if(rc != 0) {
fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(rc));
rc = 1;
goto out;
}
for(rp = result; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(sock < 0) {
perror("socket");
continue;
}
if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
break;
}
else {
perror("connect");
close(sock);
sock = -1;
}
}
if(sock < 0) {
fprintf(stderr, "Unable to connect\n");
goto out;
}
epoll = epoll_create1(EPOLL_CLOEXEC);
if(epoll < 0) {
perror("epoll_create");
goto out;
}
event.events = EPOLLOUT;
event.data.fd = sock;
if(epoll_ctl(epoll, EPOLL_CTL_ADD, sock, &event) == -1) {
perror("epoll_ctl");
goto out;
}
rc = do_epoll(epoll);
if(rc == -1) {
perror("do_epoll");
rc = 1;
goto out;
}
printf("Kill server, check socket state, and press return");
getchar();
for(i = 0; i < 5; i++) {
rc = do_epoll(epoll);
if(rc == -1) {
perror("do_epoll");
rc = 1;
goto out;
}
}
rc = write(sock, buf, sizeof(buf));
if(rc < 0) {
perror("write");
rc = 1;
goto out;
}
else if(rc == 0) {
fprintf(stderr, "socket EOF\n");
}
else {
printf("Wrote %d bytes\n", rc);
}
rc = 0;
out:
if(epoll >= 0) {
close(epoll);
epoll = -1;
}
if(sock >= 0) {
close(sock);
sock = -1;
}
if(result != 0) {
freeaddrinfo(result);
result = NULL;
}
return rc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment