UNIX & GNU/Linux - System calls - Using accept()

The accept() system call waits a connection from a client.

For the example above, we are going to take the nc tool (you can use telnet, it is the same).

If we reach the server through the nc connection, the server will shutdown.
But that's what we want to do.

Let's see it in this accept() tutorial.

Using accept()

server.c

/* server.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "h.h"

void my_socket(t_s *s)
{
    s->name    = "TCP";
    s->domain    = AF_INET;
    s->type    = SOCK_STREAM;
    s->pe        = getprotobyname(s->name);
    s->fd        = socket(s->domain, s->type, s->pe->p_proto);
    check_error(s->fd, -1);
}

void my_bind(t_s *s, int port)
{
    s->sockfd                = s->fd;
    s->addr.sin_family        = s->domain;
    s->addr.sin_addr.s_addr = INADDR_ANY;
    s->addr.sin_port        = htons(port);
    s->addrlen                = sizeof(s->addr);
    s->bindValue            = bind(s->fd, (const struct sockaddr *)&s->addr, s->addrlen);
    check_error(s->bindValue, -1);
}

void my_listen(t_s *s, int backlog)
{
    s->listenValue = listen(s->sockfd, backlog);
    check_error(s->listenValue, -1);
}

void my_accept(t_s *s)
{
    s->addrlenAccept = sizeof(s->addrAccept);
    s->acceptValue = accept(s->sockfd, (struct sockaddr *)&s->addrAccept, &s->addrlenAccept);
    check_error(s->acceptValue, -1);
}

int main(int ac, char *av[])
{
    t_s s;

    check_arg(ac, ARG_SIZE);
    my_socket(&s);
    my_bind(&s, atoi(av[1]));
    my_listen(&s, BACKLOG);
    my_accept(&s);
    debug(&s);
    check_error(close(s.acceptValue), -1);
    check_error(close(s.fd), -1);
    return 0;
}

debug.c

/* debug.c */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

#include "h.h"

void debug(t_s *s)
{
    printf("\n===== socket() =====\n");
    printf("domain = %d\n", s->domain);
    printf("type = %d\n", s->type);
    printf("fd = %d\n", s->fd);
    printf("name = %s\n", s->name);
    printf("p_proto = %d\n", s->pe->p_proto);

    printf("\n===== bind() =====\n");
    printf("sockfd = %d\n", s->sockfd);
    printf("sin_family = %d\n", s->addr.sin_family);
    printf("sin_addr.s_addr = %d\n", s->addr.sin_addr.s_addr);
    printf("sin_port = %d\n", s->addr.sin_port);
    printf("addrlen = %d\n", s->addrlen);
    printf("bindValue = %d\n", s->bindValue);

    printf("\n===== listen() =====\n");
    printf("listenValue = %d\n", s->listenValue);

    printf("\n===== accept() =====\n");
    printf("addrlenAccept = %d\n", s->addrlenAccept);
    printf("acceptValue = %d\n\n", s->acceptValue);
}

void check_error(int test, int error)
{
    if (test == error)
    {
        fprintf(stderr, "ERROR: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
}

void check_arg(int ac, int number)
{
    if (ac < number)
    {
        printf("Usage: ./server [PORT]\n");
        exit(EXIT_FAILURE);
    }
}

h.h

#ifndef H_H_
#define H_H_

#include <netdb.h>

/**
 * Define
 */
#define ARG_SIZE 2
#define BACKLOG 10
#define BUF_SIZE 255

/**
 * Structure
 */
typedef struct mystruct
{
    /* socket */
    int domain;
    int type;
    int fd;
    char *name;
    struct protoent *pe;

    /* bind */
    int sockfd;
    socklen_t addrlen;
    struct sockaddr_in addr;
    int bindValue;

    /* listen */
    int listenValue;

    /* accept */
    int acceptValue;
    socklen_t addrlenAccept;
    struct sockaddr_in addrAccept;
} t_s;

/**
 * Prototype
 */
void debug(t_s *);
void check_error(int, int);
void check_arg(int, int);

#endif /* H_H_ */

Compiling

$ gcc server.c debug.c -o server ; ./server 5000

Now that the server is launched, it's waiting a connection from a client on the port 5000.

For that we need to start another shell (it will be our client side).
We have to specified the address and the port.
As we are in local (on our system), we can use the localhost alias or if it doen't work, its real value : 127.0.0.1.

So let's type with nc:

$ nc localhost 5000

Result

The server side is quitting and it displays:

===== socket() =====
domain = 2
type = 1
fd = 3
name = TCP
p_proto = 6

===== bind() =====
sockfd = 3
sin_family = 2
sin_addr.s_addr = 0
sin_port = 4647
addrlen = 16
bindValue = 0

===== listen() =====
listenValue = 0

===== accept() =====
addrlenAccept = 16
acceptValue = 4

It's getting good! blush

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.