Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to code an epoll based sockets client in C

All the examples I can find online are servers. I want to build a basic web crawler using epoll. So I need a basic client example to get me started.

When I say basic I really mean a complete example that demonstrates multiple connections with sending and receiving of data to live web hosts. A simple HEAD request and its response for example.

like image 627
James Read Avatar asked Aug 10 '18 00:08

James Read


People also ask

What is epoll in socket programming?

epoll_ctl with EPOLL_CTL_ADD should be called once for each socket. And when epoll_wait is called, it will monitor all the sockets that are added and return only those FDs that have some events to consume.

What is Epollin?

EPOLLIN //Indicates that the corresponding file descriptor is readable (including the normal shutdown of the opposite SOCKET); EPOLLOUT //Indicates that the corresponding file descriptor is writable; EPOLLPRI //Indicates that the corresponding file descriptor has urgent data to read (this should indicate that out-of- ...

What is epoll_wait?

The epoll_wait() system call waits for events on the epoll(7) instance referred to by the file descriptor epfd. The buffer pointed to by events is used to return information from the ready list about file descriptors in the interest list that have some events available.


1 Answers

Here is a sample c code for client socket with epoll.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 22
#define SERVER "127.0.0.1"
#define MAXBUF 1024
#define MAX_EPOLL_EVENTS 64

int main() {
    int sockfd;
    struct sockaddr_in dest;
    char buffer[MAXBUF];
    struct epoll_event events[MAX_EPOLL_EVENTS];
    int i, num_ready;

    /*---Open socket for streaming---*/
    if ( (sockfd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0)) < 0 ) {
        perror("Socket");
        exit(errno);
    }

    /*---Add socket to epoll---*/
    int epfd = epoll_create(1);
    struct epoll_event event;
    event.events = EPOLLIN; // Can append "|EPOLLOUT" for write events as well
    event.data.fd = sockfd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);

    /*---Initialize server address/port struct---*/
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(PORT);
    if ( inet_pton(AF_INET, SERVER, &dest.sin_addr.s_addr) == 0 ) {
        perror(SERVER);
        exit(errno);
    }

    /*---Connect to server---*/
    if ( connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0 ) {
        if(errno != EINPROGRESS) {
            perror("Connect ");
            exit(errno);
        }
    }

    /*---Wait for socket connect to complete---*/
    num_ready = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, 1000/*timeout*/);
    for(i = 0; i < num_ready; i++) {
        if(events[i].events & EPOLLIN) {
            printf("Socket %d connected\n", events[i].data.fd);
        }
    }

    /*---Wait for data---*/
    num_ready = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, 1000/*timeout*/);
    for(i = 0; i < num_ready; i++) {
        if(events[i].events & EPOLLIN) {
            printf("Socket %d got some data\n", events[i].data.fd);
            bzero(buffer, MAXBUF);
            recv(sockfd, buffer, sizeof(buffer), 0);
            printf("Received: %s", buffer);
        }
    }

    close(sockfd);
    return 0;
}
like image 188
Murli Avatar answered Sep 20 '22 14:09

Murli